Automatic update an input number field value based on number values in other input fields - redux-form

I think I understand how formValueSelector works. But what I have not be able to figure out on how to use formValueSelector to update an INPUT field.
connect(
state => {
const { firstValue, secondValue } = selector(state, 'first', 'second')
// do some calculation
return {
sum: firstValue + secondValue
}
}
)(MyFormComponent)
In other words how do I get that sum value to be the value of on input field or global Redux state value?

There's an endpoint for such scenarios in redux-form API named as InitializeFromStateForm.
Refer here https://redux-form.com/6.6.3/examples/initializefromstate/
InitializeFromStateForm = reduxForm({
form: 'initializeFromState' // a unique identifier for this form
})(InitializeFromStateForm)
Or else there is no harm in having a new prop for the inputs you like to have an initial state fetched from store something like this.
{
sum: firstValue + secondValue,
otherInput: "initial value"
}

You can dispatch the change action from your component.
Ex:
this.props.change('formname','fieldname', this.props.sum);

Related

How to store data for use in multiple data validation using GAS?

I have a script running on Google Sheets, which brings data from another spreadsheet/file as an array and sets one of its column's data as a data validation into a cell. Then, as the user picks one option of this data validation, the script goes back to that file and brings its related data and sets it in an adjacent column and this repeats about 3 times, making the process slow.
I was wondering if that would be possible to store the first data collection into the document property and set the data validations by grabbing related information from that data set, instead of going to the other file everytime.
Here's an update, with a working version:
function listaCategorias() {
let listaGeral = sheetBDCadProd.getRange(2, 1, sheetBDCadProd.getLastRow(), 45).getValues();//Gets all values
//Extracts a column of interest for this first data validation setting
let categorias = [];
for (let a = 0; a < listaGeral.length; a++) {
categorias.push(listaGeral[a][17])
}
let uniqueCat = [...new Set(categorias)]; //Gets a list of unique values. Not sure how I'd do that within new Set, so I did a for loop before
//Sets the data validation
const cell = sheetVendSobEnc.getRange('B5');
const validationCat = SpreadsheetApp.newDataValidation().requireValueInList(uniqueCat).setAllowInvalid(false).build();
cell.clearContent();
cell.clearDataValidations();
cell.setDataValidation(validationCat);
//Saves the data into the document property for usage in the next script/data validation
listaGeral = JSON.stringify(listaGeral)
PropertiesService.getDocumentProperties().setProperty('listaGeral', listaGeral);
}
//This is getting one of the columns, based on the option picked..the one generated by the data validation above.
function listaDescricao() {
const categoria = sheetVendSobEnc.getRange('B5').getValue();
const dadosCadProd = PropertiesService.getDocumentProperties().getProperty('listaGeral')
let cadGeral = JSON.parse(dadosCadProd);
//Filters the elements matching the option picked
let filteredNomeSobEnc = cadGeral.filter(function (o) { return o[17] === categoria });
//Filters unique values
let listToApply = filteredNomeSobEnc.map(function (o) { return o[7] }).sort().reverse();
let descUnica = listToApply.filter((v, i, a) => a.indexOf(v) === i);
Logger.log('Descrição Única: ' + descUnica)
}
It's working, but I'd like to know the rooms for improvement here.
Thanks.

how to filter out the initial value but all the subsequent ones?

This notificationsCount$ is being called by several components. That's why I make one initial call the first time a component want to read the data.
this.initialLoad = false;
readonly notificationsCount$ = this.store.pipe(
select(getNotificationsCount),
tap(() => {
if(!this.initialLoad){
this.initialLoad = true;
this.loadNotifications();
}
}),
skip(1)
);
without filtering, the selector is returning 0, the initial value, and 3, the number of notifications after the call was made to backend. I want the selector to emit every value but the initial one, i.e. 0.
skip(0) still returns both values, i.e. 0 and 3. skip(1) returns 0. skip(2) doesn't return anything.
Thanks for helping
There is index argument you can mergeMap/switchMap to count the emission and depend on the index you can swallow the emission with never()
this.store.pipe(mergeMap((value,index)=>{
if(index<1) return never()
// do you stuff
}))

Need help getting the data validation criteria from "list from a range" in an apps script so I can cycle through those values

I want to get the data validation criteria from "list from a range" in an apps script so I can cycle through those values. For example, in cell A5 I have data validation set up, with "criteria" being "List from a range" and the corresponding range being "'Grade K Class MTSS Profile'!B2:AH2". I want it to return "'Grade K Class MTSS Profile'!B2:AH2" so I can cycle through this range and do something with the cells contained in that range.
This is the code I have so far:
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('MTSS Tools')
.addItem('Save All Student Reports', 'saveAllStudentReports')
.addToUi();
}
function saveAllStudentReports() {
var cell = SpreadsheetApp.getActive().getRange('A4');
var rule = cell.getDataValidation();
var ui = SpreadsheetApp.getUi();
if (rule != null) {
var criteria = rule.getCriteriaType();
var args = rule.getCriteriaValues();
ui.alert("Has rule");
ui.alert('The data validation rule is ' + criteria + args);
}
else
{
ui.alert("NO rule");
}
}
However, I'm not getting the actual range. Ideas? Thank you very much!
As you can see in the documentation:
getCriteriaValues returns:
Object[] — an array of arguments appropriate to the rule's criteria type; the number of arguments and their type match the corresponding require...() method of the DataValidation class
So args is a Range object, which means all methods from the Range class can be used, like getA1Notation:
ui.alert('The data validation rule is ' + criteria + ' ' + args[0].getA1Notation()

combineAll does not emit on empty array

JSBIN Sample
I have a changeable set of child components (POJO object) that each have its own state stream. Each time a user triggers addChild/removeChild/clearChildren, a new set of children state streams is emitted with #switchMap. So far so good! (And so amazed by RxJS!)
With Rx.Observable.from(arrayOfStateStreams).combineAll() I get a good result as long as the arrayOfStateStreams isn't an empty array.
Since this is a partial state that is combined(Latest) on a higher level, I need to get an empty array emitted or the global state tree will contain old state data that is no longer true!
I can emit some reserved token like ['EMPTY-ARRAY-PLACEHOLDER-TOKEN'], but that's just weird.
A better way would be to always append one last stream into the array so the last index can be considered trash. Still confusing code and state though.
Using [null] is not OK, since we could have a child state of 'null'.
Anyone who can solve this in a good way? Can't this be supported since there should be no other representation of an empty array after #combineAll?
Credits go to github user trxcllnt who provided the following answer:
combineAll won't emit unless the combined Observables emit at least
one value, but you could check to ensure the collection you're
combining is empty or not, and either combine or emit an empty Array:
var arrayOfStreamsStream = Rx.Observable
.of(
[], [
Rx.Observable.of('blah-1'), // component state.
Rx.Observable.of('blah-2'),
Rx.Observable.of('blah-3')
], [], [
Rx.Observable.of('foo-1'),
Rx.Observable.of('qux-2')
]
)
.switchMap(function onMap(coll) {
return coll.length === 0 ?
Observable.of(coll) :
Observable.combineLatest(...coll);
})
.subscribe(function onSubscribe(data) {
console.log('onSubscribe START')
console.dir(data)
console.log('onSubscribe END')
})
This has nothing to do with combineAll. The problem is that Observable.from results in nothing (an empty observable) when passed an empty array.
The only viable solution that I can think of if you have to get a result from an empty array is to return something else in that case.
Ann example to illustrate the problem and a possible solution.
var data = [1, 2, 3, 4, 5];
log('With data: ');
Rx.Observable.from(data)
.subscribe(function (d) { log('data: ' + d); });
// Prints:
// With data:
// data: 1
// data: 2
// data: 3
// data: 4
// data: 5
var data = [];
log('Without data: ');
var nullDataObject = { msg: 'my null data object' };
Rx.Observable.from(data.length == 0 ? [nullDataObject] : data)
.subscribe(function (d) { log('data: ' + d); });
// Prints:
// With data:
// data: [object Object]
Runnable example on jsfiddle.
When consuming this you simply filter away the object representing an empty array where appropriate.
a possible workaround is to just pipe it with startWith();
combineLatest(potentiallyEmptyArray).pipe(
startWith<any>([])
);
Note: Similar issues exist with combineLatest() (the static version) which can be solved using defaultIfEmpty() - which works, but it screws up the typing of the output.
// array of Observables
const animals: Observable<{ species: 'dog' | 'cat' }>[] = [];
// Type '{ species: "dog" | "cat"; }[]' is not assignable to type 'never[]'.
combineLatest(animals).pipe(defaultIfEmpty([]));
In TypeScript you need to either know the type of the object or use <any>[] which means you then lose typing completely.
If you have a concrete type you can use one of these:
defaultIfEmpty<Animal[]>([])
defaultIfEmpty([] as Animal[])
I often don't have a concrete type for the return value of an observable. So I came up with an operator:
export const emptyArrayIfEmpty = () => <T>(observable: Observable<T[]>) =>
observable.pipe(defaultIfEmpty([] as T[]));
Then I can add the following and get out an empty array if animals === [] without losing any typing information:
combineLatest(animals).pipe(emptyArrayIfEmpty());

How to fetch data for multiple values of a parameter one by one

I have multiple values for one parameter i want to fetch data for each query for every value of parameter in Birt report. i'm getting data only for one value of parameter not all. m using Scripted data source.Open and fetch methods.Thanks
Open in DataSet
importPackage(Packages.com.abc.test.events);
var TlantNo = params["tlant"].value;
var reqNo = params["Number"].value;
poreEvents = new StdPoreReqEvents();
poreEvents.setReqNo(reqNo);
poreEvents.setTlantNo(TlantNo);
poreEvents.open();
fetch
var poreRO = poreEvents.fetch();
if (poreRO == null) {
return false;
} else
{
row["REQ_NO"] = poreRO.getReqNo();
row["REQ_DATE"] = poreRO.getReqDate();
return true;
}
A report parameter with multiple values is an array, we have to iterate on it through the scripted dataset.
In open event of the dataset, we only have to initialize a global index:
i=0;
In fetch event, process each iteration with something such the script below. Pay a special attention how we get the value of reqNo:
importPackage(Packages.com.abc.test.events);
if (params["Number"].value!=null && i<params["Number"].value.length){
var TlantNo = params["tlant"].value;
var reqNo = params["Number"].value[i];
//ETC. do here your stuff with porevents, declare poreRO, check if result is null
row["REQ_NO"] = poreRO.getReqNo();
row["REQ_DATE"] = poreRO.getReqDate();
i++; //Important: increment this even if poreRO is null, otherwise infinite loop
return true; //should return true even if poreRO was null, to process next rows
}else{
return false;
}
The other approach is to do this problem is by defining a dataset having output column which is the multiple value parameter Fetch that column by IN query of the multiple value parameter then pass that value means(output column value) to the other datasets as a Input/output parameter and give binding to parameter.
It resolved my problem :)

Resources