Adobe DTM rules based on Data Element activation - tags

I tried to condition Page-load rules (Custom criteria) on Data Element activation, in order to fire them only if Data Element are active.I mean the real Data Element activation in its Adobe DTM editing interface.
I attempted the condition below:if (typeof _satellite.getVar('DataElement_name') != 'undefined') {
return true;
} else {
return false;
}because I discovered that an inactive Data Element makes "getVar()" method return "undefined".This does not work, and the rule is fired anyway.This was my second chance, after a first attemp to use the built-in method "isRuleActive()".Unfortunately this seems to always return true, even if the Data Element is inactive.But then, I'm not sure if Data Element could be used with this method.My scenario concerns some Page-load rules built upon Data Elements, which are explicitly called with "getVar()" into their custom code.If those Data Elements are inactive, the rules will go wrong and javascript errors will come up.This is the reason why I'd like to add a Custom criteria condition to these rules, based on Data Element activation.Thanks

What are the possible returns of your data element?
You can try to use this method to check out the returns:
_satellite.dataElements.Your-data-Element-name.customJS();
I recommend that you make your data element return false and in your rules you can choose criteria for "data element value".
Hope this helps!

Related

Running into an issue with a mutation and component flickering with react-query

So, I am making a query everything my context API is updated via a form selection update..
So, order of operation is like so.
User makes a change to a form by selecting (one of possible many) from dropdown.
Change updates "context api" which resaturates the parent component.
Because the form key/values changed, I fire a mutation.
Mutation returns a value. So far, great.
But, when I repeat step #1 - #4, another component flickers with that updated value because at some point the "const" that is expecting a value is undefined... THEN, it has a value..
So, like so..
has a value...
...query api call...
has no value
...returns query
has a value
const ProductPage = (props) => {
const { question } = useContextStateWhatever();
/* Queries */
const { data = {}, isFetched } = useProductUpdatePrice({ questions });
const value = derivePriceFromResponse(data.products);
return (
<SomeComponentRendered value={value} />
)
So, you can see between the "old value" and request in query, that the passed "value" will be undefined. Then query returns, updated value.
I was hoping the query will return any previous value, but the "queryKey" changes with every selection of the form. Deep queryKey.
I was hoping I wouldn't have to then put this value into local state from within a useEffect, or use useRef and create hook to hand back "previous" value until new value is ready.... That's not what react-query is for, right? I mean, shouldn't I be able to make a query call whenever the "context api" changes, and not expect this latency diff of undefined. Any strategies to over come this?
Since the "queryKey" is different (mostly for normal form interaction) for each query, I can see how it can't hand back a previous value until it resolves etc.. any ideas?
Any thoughts?
I think the keepPreviousData: true option is what you are looking for. If the query key changes, you will the get the data from the previous query key, along with an isPreviousData: true flag. The background update will still happen, and then you’ll get the data for the new query key once it arrives. The query will stay in isSuccess status the whole time.

How to call (filter-) valueGetter functions for external filter in ag-grid?

I am using ag-grid with angular and I want to apply an external filter to it.
The documentation shows an example what the doesExternalFilterPass function can look like:
function doesExternalFilterPass(node) {
switch (ageType) {
case 'below30': return node.data.age < 30;
...
default: return true;
}
}
It basically uses the raw data to filter the rows. As I use the columns valueGetter/filterValueGetter functions to modify the values, I want the external filter to filter based on the return values of these functions but I haven't found the proper way to do this.
I can get the value that I want by calling
this.gridOptions.api.getValue(columnId, node);
(which calls the valueGetter under the hood) instead of
node.data[columnId]
but I didn't find any example doing it that way.
So I am asking for the right way of calling the valueGetter functions inside doesExternalFilterPass or how anybody else approached this problem.
(It is especially important when you have rows that are not even included in the data object. This is the case when a columns values are calculated through a valueGetter/filterValueGetter function e.g. by adding two other columns.)
Instead of using a valueGetter, you can add a custom field to your data model that you compute before feeding data to the grid. You will need to pre-process the data and then use this new field in column definition and external filter.

how to pre-set column filter in ag-grid

I have an Ionic/Angular app using ag-grid. I would like certain grids to have a filter automatically applied when the grid is loaded - without the user having to do anything.
I tried the following:
onGridReady(params) {
params.api.sizeColumnsToFit();
// get filter instance
var filterComponent = params.api.getFilterInstance("isActive");
// OR set filter model and update
filterComponent.setModel({
type: "greaterThan",
filter: 0
});
filterComponent.onFilterChanged();
}
but it did nothing. Any ideas?
Edit: AgGrid included a onFirstDataRendered callback in version 24.0, as stated in later comments. The original answer below is now only relevant for versions which pre-date this functionality.
onFirstDataRendered(params) {
var filterComponent = params.api.getFilterInstance("isActive");
filterComponent.setModel({
type: "greaterThan",
filter: 0
});
filterComponent.onFilterChanged();
}
Reproduced your problem in a couple of their example older plunks, seemed to be alleviated by adding a small delay. Just venturing a guess that maybe the DOM isn't completely ready yet, although the grid is.
Pre-onFirstDataRendered versions:
onGridReady(params) {
params.api.sizeColumnsToFit();
setTimeout(() => {
var filterComponent = params.api.getFilterInstance("isActive");
filterComponent.setModel({
type: "greaterThan",
filter: 0
});
filterComponent.onFilterChanged();
},150)
}
I ended up doing this.
var FilterComponent = gridOptions.api.getFilterInstance('Status');
FilterComponent.selectNothing(); //Cleared all options
FilterComponent.selectValue('Approved') //added the option i wanted
FilterComponent.onFilterChanged();
I think the problem is, that the grid resets the filter when new rows are loaded. There are multiple ways to approach this:
The predefined filter types have a filter parameter called newRowsAction
https://www.ag-grid.com/javascript-grid-filter-text/#params
newRowsAction: What to do when new rows are loaded. The default is to reset the filter. If you want to keep the filter status between row loads, then set this value to 'keep'.
This answer suggests to set the gridOptions property deltaRowDataMode=true
You can also listen to one of the grid events that are emitted when the grid date changes and then apply the filter
https://www.ag-grid.com/javascript-grid-events/#miscellaneous: rowDataChanged, rowDataUpdated
These should all keep the filter when the data changes but I think you still need a bit of extra logic (setting a flag) if you want the filter only on the first load.
In my case I need to restore Ag-Grid's Set Filter when grid loads. Inspired by the accepted answer, my understanding is the filter instance api can only be accessed after grid data is ready (NOT gridReady), as it needs to aggregate row data to populate its filter list.
Therefore, as #3 adviced in #Fabian's answer, I have set up event listeners when row data changes.
You can also listen to one of the grid events that are emitted when the grid date changes and then apply the filter https://www.ag-grid.com/javascript-grid-events/#miscellaneous:
rowDataChanged, rowDataUpdated
In a similar use case I believe this is a better approach than set up an arbitrary timeout number before accessing the filter instance as it may end up with inconsistent results.
v24.0.0
The best way to implement this, is to apply your default filter in the firstDataRendered callback.
e.g.
onFirstDataRendered(params) {
//... apply your default filter here
}

Handling more complex forms

In my current project I have to deal with more complex forms. Fields (i'll name them 'A' and 'B') are automatically filled if a specific field (i'll name that one 'C') received user input. But also if the user inputs data into field A, the fields B and C are automatically filled out.
(This is only a simple example, the current logic is a bit more complicated)
What I have to take care of is that no cycles happen (C -> A -> C -> A -> ...). So I need to now if the current value change was due to user input or another field that had received input and then triggered the value change of the current field. And I also need to now in the second case which field exactly triggered the value change because then I must trigger other specific actions corresponding from who/what triggered that value change.
Is there a general approach in Vaadin to deal with this kind of form
structure? The problem at the moment is that I simply don't now who
or what triggered what ValueChangeEvent.
Are there frameworks to deal with this or am I overlooking an existing Vaadin pattern?
Handling of valueChange events in Vaadin is a bit of pain, since it always fires, no matter if the user has changed something, or the application has used setValue(....) on the component.
The only solution for this is to remember when you do a setValue(....) in your application and then disable the trigger code in the other components.
For example in this case (endless loop):
field1.addValueChangeListener( field2.setValue('Updated by field1');
field2.addValueChangeListener( field1.setValue('Updated by field2');
Change it that way:
boolean inTrigger= false;
field1.addValueChangeListener(
{
if (!inTrigger)
{
inTrigger= true;
field2.setValue('Updated by field1');
inTrigger= false;
}
});
field2.addValueChangeListener(
{
if (!inTrigger)
{
inTrigger= true;
field1.setValue('Updated by field2');
inTrigger= false;
}
});
That way you can prevent update loops and let execute your code exactly once.

Write to database only when a button is pressed

I have a form with two datasources that are linked by using an outer join. It is written to the database by using Form Datasource Unit of Work framework.
As of now, the data gets written when moving from one datasource form control to another form datasource control. I want to only activate/write using Form Datasource Unit of Framework when a button is clicked.
Is there a way to prevent automated write function when moving from one Form Control to another?
First have a look on HowTo: Unit of work implementation for a Form to check you align with that. The official doc is Change Group and Optional Record Modes.
The writes are issued because you are "leaving" a record, see Event Method Sequences when Focus is Removed from a Record.
This is the sequence when validateWrite returns true:
leaveRecord return true
validateWrite return true
writing
written
leaveRecord return true
leaveRecord return true (again)
This is the sequence when validateWrite returns false:
leaveRecord return true
validateWrite return false
leaveRecord return false
So you can override validateWrite to silently return false, when you do not want to save. Be sure to call super() when you do want to save!
Or you can call leaveRecord yourself to force a write:
if (record_ds.leaveRecord(true))
{}
When calling record_ds.leaveRecord(true) please observe that it may not save the record, e.g. if validation fails. In that case leaveRecord will return false.
Observe that you are working "against" the standard working, this will make your form work differently than other forms.