I have an onchange event in a input tag of type checkbox that calls a javascript function and pass three parameters from the model to the function:
<input type="checkbox" ... onchange="changeRow('#Model.Id', '#Model.Type', #Model.AwaitingApproval)" ...
In the changeRow javascript function the first two values are reported correctly, but the third parameter (which is of type boolean) is a reference to an onchange function. When inspecting the value, I can see the onchange function signature and it states that it is a function.
This is a normal MVC application with some jquery and the data is communicated through ajax calls from the controllers that serves the data through the Model.
If I change the code to the following:
<label>#Model.AwaitingApproval <input type="checkbox" ... onchange="changeRow('#Model.Id', '#Model.Type', #Model.AwaitingApproval)" ... </label>
Then the value TRUE is printed on the page before the checkbox. So, that proves that the model value is correct and can be referenced.
Any ideas on what might be causing the weird behavior in the js function would be greatly appreciated!
(Or an explanation of this behavior if it is expected and I am not understanding why this happens.)
Javascript function:
function changeRow(Id, Type, AwaitingApproval)
{
if (!AwaitingApproval) (*This is where I first detected the problem*)
{
...
}
}
There is nothing "special" about the javascript function, it simply receives the parameters and then does processing based on the values.
The Id parameter has the correct integer value, the type field has the correct string value, but the AwaitingApproval parameter has the following:
function onchange(event)
{
changeRow('7334512', 'targeted', onchange)
}
Which is basically the reference to the function I have assigned to the onchange event in the first place, and you guessed it, the onchange in the third parameter is yet another reference to the same function, causing an endless reference loop in the same way.
With some more playing, I thought to give it a try by enclosing the third parameter in a code block:
onchange="changeRow('#Model.Id', '#Model.Type', '#{ #Model.AwaitingApproval }')"
which then results in the correct boolean value stored in the property.
I do not understand this behavior at all and would love if someone can shed some light on this.
A cleaner way as suggested by Stephen Muecke
onchange="changeRow('#Model.Id', '#Model.Type', '#Model.AwaitingApproval.ToString()')"
It is important to remember the quotes and then test for string values ('True' / 'False') in the javascript function.
In your first example <input type="checkbox" ... onchange="changeRow('#Model.Id', '#Model.Type', #Model.AwaitingApproval)" ... you have your #Model.AwaitingApproval parameter without ''. So maybe try onchange="changeRow('#Model.Id', '#Model.Type', '#Model.AwaitingApproval')"
Related
If I have multiple functions passed to a click event i.e.
#click="
inputHandler();
sendToken(computedUser.email);
responseMessage();
"
The function with an event parameter:
inputHandler(e) {
// code
}
Won't run. If I pass it on it's own:
#click="inputHandler"
It works fine.
Why is this and how can I get around it?
Internally Vue uses some RegExps to decide what form of event handler you're using.
If it seems to be the name of a method it will call it and pass the event.
If it seems to be inline code it'll just run it. In this case the event object is accessible as $event.
So:
#click="inputHandler($event)"
is roughly equivalent to:
#click="inputHandler"
Strictly speaking these aren't quite the equivalent, for example with component events that emit multiple arguments you'll only get the first one using $event like this.
See https://v2.vuejs.org/v2/guide/events.html#Methods-in-Inline-Handlers
For a deeper understanding see the Vue source code:
https://github.com/vuejs/vue/blob/0baa129d4cad44cf1847b0eaf07e95d4c71ab494/src/compiler/codegen/events.js#L96
Give your eyes a few minutes to adjust and it isn't too difficult to understand.
Personally I try to avoid anything more complicated than a single method call in the inline listener. Instead I'd suggest having something like #click="onSendClick" and let the method onSendClick worry about the details.
If I recall correctly, vue creates a wrapper function, if the passed value isn't a function. So
inputHandler();
sendToken(computedUser.email);
responseMessage();
actually get's turned into
function wrapper(){
inputHandler();
sendToken(computedUser.email);
responseMessage();
}
And as you can see the arguments passed to wrapper are lost.
The easiest way to fix this is probably to create a new method that accepts the event parameter and calls all of your function and use that one in the event handler.
Hi so I am just wanting to understand how javascript/react is handeling whats going on when I have a function triggered from an event . Im going to show three different code segements, 2 of which work, one of which didnt, and see if I am understanding them correctly. :)
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={() => this.setField()}>
this doesnt work because it is passing a null value to a function that expects a value, in this case e. however, if the function was just submitting something already in state, that would be reasonable way to do it.
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={(e) => this.setField(e)}>
this works because it is getting the event as e and then passes it to the function. How does it know to associate the event to e? does this functionality extent to other things when dealing with html?
setField(e){console.log("in setfield", e)}
<select multiple className="form-control" id="sel2" name="sellist2"
onChange={this.setField}>
This one I really dont understand why it works, but it does. I am assuming that it inherently know to pass the event as default to the function. again does this inbuilt logic occur anywhere else, maybe not neccessarily for events?
Thanks again. Im new to javascript so it is interesting to learn all the idosyncracies of javascript. sadly most of then learning is through frustration of debugging!
All functions in javascript can be passed an arbitrarily large number of parameters, even if the function doesn't do anything with them. For example, the following is legal, if useless:
function thingThatExpectsZeroParams() {
console.log('hello');
}
thingThatExpectsZeroParams(1, 2, 3, 4, [5], 'six');
Six pieces of data were passed into the function, but nothing happened with them because the function didn't do anything with them. To get access to the values passed in, you just need to pick a name that you're going to call it. This name is local to your function and can be anything you want.
function callback(event) {
console.log(event);
}
// I could also just have easily called it something else, and the code would work just as well
// function callback(quesoBurrito) {
// console.log(quesoBurrito);
// }
callback('hello');
So when you set up a listener like this:
onChange={() => this.setField()}
Your function will be called, passing in the event object. But since your function doesn't give the first parameter a name, you have no way to access it, and then when you call this.setField, you pass nothing in there either.
In contrast, with this listener:
onChange={(e) => this.setField(e)}
Your function will again be called, passing in the event object. This time, you named that argument 'e', and can then do with it what you will, in this case forwarding it along to setField.
And when you do this:
onChange={this.setField}
You cut out the middleman. this.setField will get called directly, passing in the event object. Presumably, setField is expecting this, and does something with the object it was passed.
It's not complicated. Whatever Javascript function you assign to onChange will get called at the appropriate time and passed one single argument generally known as e. You can give that argument any name you want in your function (or not declare it at all), but the first argument will be there.
So, when you do this:
onChange={() => this.setField()}
You are ignoring the argument passed to your event handler and then inside that event handler you're calling this.setField() which to no surprise does not pass any argument to setField(). In reality, what's actually happening is this:
onChange={(e) => this.setField()}
How does it know to associate the event to e? does this functionality extent to other things when dealing with html?
The DOM specification says that when an onChange event handler is called, it will be passed the e object as the first argument (whether you declare it or not, it's there as the first argument to the function). This is just how callbacks work in Javascript. The caller of the callback decides what arguments they are going to pass the callback. It's up to you when you declare your callback whether you declare the argument and use it or not. Regardless of how you declare it, the caller passes it.
For this section of code:
onChange={this.setField}
You are say that the function you want to be the onChange event handler is your setField() method. So, no surprise, when the DOM calls that method, it will pass the event object as the first argument just like in the above example.
This one I really dont understand why it works, but it does. I am assuming that it inherently know to pass the event as default to the function. again does this inbuilt logic occur anywhere else, maybe not neccessarily for events?
As described earlier the DOM specification is where this event handler is specified. In the definition of that, it describes what arguments will or won't be passed to whatever callback function you register as this event handler. This is true of all callbacks in Javascript. The caller decides what it will pass to the callback. This is not specific to this type of event handler. Callbacks are used lots of places in Javascript. Even something like array.filter() takes a callback and it's the caller of the callback (the implementation of the Array object in that case) that determines what arguments are passed to the callback.
*Don't mind the jQuery syntax. It serves as an example only and not the focus of the question.
$('target').on('click',function(){
'do something'
},5);
What does the value of 5 do? Does it set an initial value? Can you have multiple values like:
},5,6,5);
or can you only have one value?
They are simply function parameters. There is nothing special about the 2nd parameter, which happens to be a function. For the sake of clarity you could also refactor the code to look like this:
$('target').on('click', doSomething, 5);
function doSomething(){
// do something
}
To see exactly what parameters you can pass to the .on() function I'd recommend reading the documentation.
This argument passes value to handler.
You can get value from event.data.
It must be single value.
If you want to pass multiple data, pass value by object.
$("button").on("click", 3, function(e) {
alert(e.data) // alert 3
});
Reference: http://api.jquery.com/on/
While editing an angular textbox marked as "required", I am unable to delete the 1st letter. However if I move my cursor to before the 1st letter, and enter some text and then delete the last letter left earlier, I am able to do my required edit.
Note: No such issue being observed while creating a new record.
Please find the sample code being used.
<input type="text" class="form-control" ng-model="vm.xyz.firstName" ng-model-options="modelOptions" required />
Used library version: angular: 1.3.15, bootstrap:3.3.2
Thanks in advance.
This is the expected behaviour as per documentation:
If the validity changes to invalid, the model will be set to undefined, unless ngModelOptions.allowInvalid is true.
Since you set your field as required, when it becomes empty, it becomes $invalid, which in turn sets your model to undefined. If you add allowInvalid: true to your ngModelOptions settings, your model will be allowed to receive the empty string value instead of undefined. Plunkr here.
As described by #leonardo-braga, this happens because the field becomes invalid upon deletion of the last character and the $modelValue set to undefined (which tricks your getter/setter into believing it has been called in "getter" mode).
A similar question has been answered on GitHub.
Copying here for easier reference:
Using allowInvalid will work around the issue, but it is not solving the actual problem.
The actual problem lies in the implementation of the getter/setter function, which treats passing an argument with value undefined as passing no argument at all (although these are obviously two very distinct cases).
You should use a more "accurate" way of defining whether the function is called as a getter or as a setter (i.e. whether an argument has been passed (even if undefined) or not).
E.g.:
getterSetterFn: function (newValue) {
if (arguments.length) {
_value = newValue;
}
return _value;
}
See, also, this short demo.
Does javascript not check function parameters when invoking.
This function "test" below fires even though it is being called with no parameter.
<input type="button" value="test" onclick="test()">
test = function(param){
alert("test");
}
fiddle :
http://jsfiddle.net/Yazpj/1912/
Should an error not being thrown or does the javascript engine/parser not even check function parameters when finding what to call. Does this have any implications for overriding functions ?
No, JavaScript does not check parameters.
Extra parameters will be ignored. Parameters declared but not passed will have a value of undefined. All passed parameters (declared or otherwise) will appear in the arguments pseudo-array.
There are no implications for overriding functions because JS does not support overriding functions.
Libraries such as jQuery that have methods with multiple signatures use a single function that figures out the type of the passed parameters and then performs the required action.
You have to check on your own:
var test = function (param) {
if (typeof param === 'undefined') {
// do something...
}
};
Javascript is a really flexible language and this is just one example of it. Unless you are not accessing the param it won t rise any error e.g. param.sender
As for your override question it is sort of true. Every Javascript function has a arguments variable which is the array of passed parameters. if you give name the parameter defining the function JS just give it to you according to order.
But overriding is another story the overriding is achieved by checking the arguments element sometimes just length of the array sometimes type of the individual item.
For example; when you call $("#name").val() as there is no item it just return the value if arguments has values this time jQuery user proper assignment e.g. element.value = arguments[0]