ReactiveForms valueChanges in dom vs component - javascript

I'm wonder if there's a way to know the difference whether valueChanges on a FormControl was triggered from the dom or the component itself. My use case is I need to do stuff() when the user changes the value, but I don't want to do stuff() if the value changed as a result of something else. Any thoughts?

with the control ".touched"
EXAMPLE:
YourModelForm.get('YourField').touched
the value becomes true when the user enters a value (first click on the field, enter the value, tab or click out of the field).
I tried with a call rest and the value remains to false, try it if you can possibly it works for your situation. :-)

Thanks to #Nobady, who inspired the idea. I found there's actually an option for setValue on the formControl called emitEvent. Using this, I can make it so if I update the value programmatically I can bypass the valueChanges getting called.

Related

model input (textfield) statemachine in xState

Would love to read your thoughts on how you would model a input (textfield) with xState.
According to an input ux article a textfield could have following states:
Input text fields can have one of the following states: default, focused, error, and disabled. All states should be clearly differentiated from one another.
This makes sense as other libs like Material UI uses more or less the same states.
Im wondering how to model this.
Let me just write down some thoughts:
I think its obvious that the value should be part of the xState context as it could have any value
the mentioned states makes sense as well
Now the part where im not so sure: lets say we have an inline validation (onChange) which says the textfields value is ok and for that we set want to set with css a class "valid" which gives the textfield a green border.
We would need either a state transition from default to default_valid (not just valid because we are still in the default state) ... the same applies for default_invalid ... and aswell for some more combinations which would possible end in a state explosion.
model it in xState as a child state and access it via default.valid or default.invalid ...
In both scenarios we would need in the textfield component another mapping which reads something like
(just pseudocode)
switch(state) {
'default.invalid': setColor(red), setDisabled(false)
'default.valid': setColor(green), setDisabled(false)
'default.valid.submitting': {
setColor(green)
setDisabled(true)
}
Im really not happy with this approach to manage the state in the component and time in xState machine. This just seems wrong to me.
I would prefer to just use the input machines states ... which works well for some default like, default, focused ... but as soon as the field is "in 2 or more states" it gets a mess.
One way would be to just keep some high level states and write the additional ones in the context and just pass it to the textfield? (sounds not that good either tbh)
So would love to hear your thoughts how you would model something like this.
You can use state.matches(...) to clean things up, and/or you can place those actions directly in the states they're relevant for, e.g., in entry or exit.

Angular 4 Binding function in template file

I need to check some condition in angular. So I use the following method.
<span> {{checkValue("test")}} </span>
Then My component like
checkValue(val){
if ("test" == val){
return "value is true"
}
}
in this case the function call continuously.
Is this correct method or suggest me any other idea. Thanks in advance.
The code in you example is perfectly valid, function will be triggered at every change detection pass, there must be something else that triggers change detection i.e. setInterval, http calls and so on.
As #trichetriche mentioned
Binding a variable to a template means that at every lifecycle step,
Angular will check this variable. In the case of a function, it will
call it. You can't stop that (for all I know), and you should not,
otherwise Angular will stop checking for changes on your variables.
You should avoid doing this. I believe you should try find the best solution before doing this.
In your case you can check this in html itself. So it will return true or false.
Try this
<span *ngIf="val =="test""> value is true </span>

How do I check keystroke on blur using vue?

It's not stated clearly in vue documentation nor did I find any similar questions online so I'm asking it here.
I need a vue text input to return what the last keystroke is. The method that was tied to the blur event contains a data object so I cannot capture the default event object. I tried using custom key functions but blur always trigger before them so the execution order is wrong.
In the example below "abcdef" is the data object tied to the input control. (I removed the < > signs because the stackoverflow cannot parse it.)
<input
type="text"
v-model="abcdef.amount"
#keyup.esc="cancelChange()"
#keyup.enter="saveValue(abcdef)"
#keyup.tab="saveValue(abcdef)"
#focus="saveOriginalAmount(abcdef)"
#blur="revertOriginalAmount(abcdef)">
In my vue methods
methods: {
cancelChange(): {} //Triggers revertOriginalAmount
saveValue(obj): {} //Save value
saveOriginalAmount(): {} //Save the original value.
revertOriginalAmount(): {} //Revert the value to original value
}
When the tab key is triggered, revertOriginalAmount() is immediately invoked before saveValue. Thus, the original value was saved instead of the current value. I tried setting a timeout in revertOriginalAmount to delay the saving (500ms) but it doesn't work. Futhermore, that is only a cheap hack to fix an underlying issue which is to detect what keystrokes trigger the blur function.
So what should I pass in the parameters of #blur to get the event object?
See $event in https://v2.vuejs.org/v2/guide/events.html#Methods-in-Inline-Handlers .
#blur="revertOriginalAmount(abcdef, $event)"
$event contains the event object.
methods: {
revertOriginalAmount(dataObject, event): {} //Revert the value to original value
}

javascript variable does not pass correct value to jquery click event handler (probably a scoping issue)

This is my first question on stackoverflow so hopefully I'm doing it right.
I ran into an issue where a variable was passing a seemingly strange value through a click event. I figured out a different way to do it, but I'm curious as to why my original method wasn't working. I have a feeling it is a weird scoping rule of JS, so if someone could clarify, that would be great. The code was supposed to switch back and forth between two tabs on a click event. I'm sorry if this has already been answered, but in looking at others' questions I couldn't really tell if it was the same issue that I was having.
This was my original code, where at program start tab1 had the class active-tab:
$("#tab1").on('click', {activeTab: $("#tab1").hasClass("active-tab"),
tab1Clicked: true}, changeTab);
$("#tab2").on('click', {activeTab: $("#tab1").hasClass("active-tab"),
tab1Clicked: false}, changeTab);
and elsewhere
function changeTab(event) {
var tab1Active = event.data.activeTab;
var tab1WasClicked = event.data.tab1Clicked;
if(tab1Active) {
if(tab1WasClicked)
alert("tab1 active & clicked, no change");
else {
alert("tab1 active, tab2 clicked, change");
$("#tab1").removeClass("active-tab");
$("#tab2").addClass("active-tab");
}
}
else {//tab2 is active
if(tab1WasClicked) {
alert("tab2 active, tab1 clicked, change");
$("#tab2").removeClass("active-tab");
$("#tab1").addClass("active-tab");
}
else
alert("tab2 active & clicked, no change");
}
}
The problem was that, although the .hasClass calls returned the correct result, the value of event.data.activeTab always turned out to be true, so once tab2 got clicked it never made tab1 active again because it always thought it already was, even though the class did in fact get removed. I solved this by passing only tab1Clicked through event.data and just checking $("#tab1").hasClass("active-tab") directly in the function changeTab, which is probably what I should have been doing from the beginning, but still, can someone explain to me why this other method didn't work equally well?
The "data" expressions are evaluated once, at the point where the event handler is set up. They aren't (and can't be) re-evaluated for each actual event. This code:
$("#tab1").on('click', {activeTab: $("#tab1").hasClass("active-tab"),
tab1Clicked: true}, changeTab);
is evaluated by computing the value expressions for that data object. What's passed to the jQuery .on() function therefore is an object with two properties, each with a fixed value (booleans, in this case). They'll never change after that, because there's no trace of the expressions that initialized the property values.
In this case, the simplest solution is to simply move the tests into the function, as you say.

Unable to save changes made to entity when calling javascript function through custom ribbon button event

I'm trying to create a simple function which, when ribbon button is pressed, sets entity attribute value to null.
Now the problem I am facing is, that the changes I make to the entity are not saved, form reloads and returns previous value.
To the button event I pass 'Task' activity attribute 'actualend'. 'Actual End' field is disabled by default.
ClearField: function (field) {
if (Xrm.Page.getAttribute(field) == null) return;
Xrm.Page.ui.controls.get(field).setDisabled(false);
Xrm.Page.getAttribute(field).setSubmitMode("always");
Xrm.Page.getAttribute(field).setValue(null);
if (Xrm.Page.data.entity.getIsDirty()) {
Xrm.Page.data.entity.save(); //also tried addOnSave(function)
}
}
Following debugger I was able to track that all changes are made correctly, except that on save() method they are 'discarded', then form reloads with previous value. This code works fine with CRM UR8 yet with CRM UR13 it does not.
Am I missing something?
As Guido mentions in his comment the code looks good which leads me to think that one of your two if statements is failing.
The first one obviously will fail if it is set to null. A little bit less obvious is that it will fail as well as if the field is not actually on the form (even though it may be a valid attribute of the entity). So step 1, ensure that your field exists on the form.
The second one I'm not sure of... I don't think getIsDirty() is keeps track of programmatic changes, so even though your programmatically updating a field and setting it to always submit, it may be returning false. Regardless of how exactly it's working, the if statement really isn't needed. The Xrm.Page.data.entity.save function will only actually save if it has some value that has changed, so I'd remove your dirty check regardless.
Eh, the problem with my issue all this time was that even though the field existed in the form, it never had an entity passed to it, therefore it was unable to save it. I've edited a ribbon button so to pass entity through CrmParameters and the issue was gone. Thank you both for supplying me with possible solutions regardless!

Categories

Resources