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.
Related
I'm trying to watch the value of ng-model whilst also using the minlength validation. The problem is the model value remains empty/undefined until the validation criteria is met.
HTML
<input ng-model="xyz" minlength="8" />
JS
$scope.$watch('xyz', function(val) {
// Will either be undefined or a
// string bigger than or equal
// to 8 characters.
console.log(val);
});
I know I could just substring the element's value, but this code is implemented in a directive which uses $compile, so ideally I'd prefer to watch the model value.
Any thoughts on how to resolve this?
https://docs.angularjs.org/api/ng/directive/ngModelOptions
allowInvalid: boolean value which indicates that the model can be set with values that did not validate correctly instead of the default behavior of setting the model to undefined.
When validation fails on an input, the model is being set to undefined. Is there a way to prevent this. I'm on Angular version 1.4.8.
E.g.
<input id="name" ng-model="inputname" minlength="4">
When I insert some value here and then reduce it to less than 4 characters the model inputname becomes undefined.
Figured this out, there is an option under ngModelOptions called allowInvalid which allows the modelValue to be updated with the viewValue even if it is invalid (instead of the default behaviour of setting it to undefined).
From the documentation:
allowInvalid: boolean value which indicates that the model can be set with values that did not validate correctly instead of the default behavior of setting the model to undefined.
In an answer I gave to another SO question I was very proud of having come up with a very short click-handler-toggle. Slightly re-written, it's this:
document.getElementById("myToggle").addEventListener("click", function() {
(this.oddClk = !this.oddClk) ? oddHandler() : evenHandler();
});
This isn't central to my question, but in case you're wondering what I'm doing here, read this paragraph. I'm adding a custom property, oddClk, to the HTML element I clicked. After the first click, this property is initially undefined but then is immediately negated to true. (Note that the first part of the ternary statement intentionally uses = not == or ===.) The second time through it's negated again to false, etc. Based on its value, one of two handlers is invoked. Not only is the code short, but it also doesn't require any global variables, and can be used on multiple targets simultaneously. If you're interested, here's a working version:
document.getElementById("myToggle").addEventListener("click", function() {
(this.oddClk = !this.oddClk) ? oddHandler(): evenHandler();
});
function oddHandler() {
document.getElementById("result").innerHTML = "odd";
}
function evenHandler() {
document.getElementById("result").innerHTML = "even";
}
<div id="result">Not clicked yet</div>
<button id="myToggle">Click me to toggle</button>
My question, though, is this: What are the consequences of using this.myCustomProperty where this is an HTML element (in this case, the target that was clicked)?
Note that I'm not setting a custom attribute on the element. Rather, I'm setting a new custom property on the HTML element. It actually ends up being the only own property on the element. Are there any significant side-effects of assigning an own property onto an HTML element object like this, side-effects that might have negative consequences elsewhere?
I've found other questions on custom attributes, but that's clearly a different kettle of fish. And references to this in discussions of addEventListener don't seem to bring up new own properties.
One possible down-side is that I might pick a property name that will be defined in future versions of HTML. In that case my own property would clobber the newer inherited property. However, if I name my property carefully or strangely enough, I should be OK on that front. So, are there other problems?
Note that I'm not really asking to see if I should include this in production code. I wrote my toggle routine above basically just as a mental exercise, to see how short I could write it. I'm asking more just to better understand the inner workings of HTML.
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')"
I am a beginner in Knockout and I must say I often get confused regarding when to use (). Is there any general tip/trick regarding when would you use () against when you would not because at the moment I am just doing trial and error. If the binding throws error or doesn't update values I remove () else I put.
I feel like the existing answers skip over a very important point of confusion: data-bind attributes.
It is true that you use the parens when you are in Javascript, and getting or setting observables. But when you are writing data-bind="text: property", you leave out the parens even when working with observables.
Edit
As noted in the comment below, bindings that are expressions, or access properties of observbles, require parens
visible: personName().length > 0
visible: person().Name().length > 0
visible: person().isVisible
Note that the last one person and isVisisble are both observables, but the last property doesn't use parens! The reason for this is that we would be passing a value to the binding instead of an observable, and it wouldn't update.
You use () in knockout when using observables or when executing any other method.
Knockout observables are functions, invoked to return you what you looking for or allow you to assign new values.
In knockout you use object.property() to retrieve a value and object.property(newValue) to assign a value to that property.
On the knockout website checkout the documentation, specifically the section on observables, which shows you the use of the () when querying and writing observables.
To quote:
var myViewModel = {
personName: ko.observable('Bob'),
personAge: ko.observable(123)
};
To read the observable’s current value, just call the observable with no parameters. In this example, myViewModel.personName() will
return 'Bob', and myViewModel.personAge() will return 123.
To write a new value to the observable, call the observable and pass the new value as a parameter. For example, calling
myViewModel.personName('Mary') will change the name value to 'Mary'.
To write values to multiple observable properties on a model object, you can use chaining syntax. For example,
myViewModel.personName('Mary').personAge(50) will change the name
value to 'Mary' and the age value to 50.
Knockout's interactive tutorial is also quite nice and well worth going through.
Basically whenever you're working with an observable value (array or otherwise) you should use the parentheses to get the value and set the value.
var something = ko.obserbable();
something(5); //set value
console.log(something()); //get value: 5
The reason being that most JS implementations do not support getters and setters for properties yet, so observables were implemented like this to get around this limitation.