ngChange on input changed by a select - angularjs

I have a simple select input field where the user can choose an option:
<select class="form-control" id="calc-masterbatchCode"
ng-options="masterbatch as masterbatch.code for masterbatch in masterbatches"
ng-model="$parent.materialTAB.selectedMasterbatch">
</select>
as you can see the selectedMasterbatchobject is stored in a parent controller.
Then i have a disabled input field in the order to show the property of the selectedMasterBatch:
<input type="text" class="form-control" id="calc-masterbatchPercentage"
ng-model="$parent.materialTAB.selectedMasterbatch.percentage"
ng-change="onMasterbPercentageChange()">
It works, but the problem is the ngChangedirective:
because it doesn't fire the onMasterbPercentageChange function when the user select another masterbatch.
The only way to fire that function is to type something manually into the calc-masterbatchParcentageinput field.
My goal is:
the user select a masterbatch, then he can see the masterbatch's property (the percentage) into the disabled input field and, when this one change, the onMasterbPercentageChangefunction is fired.

ngChange directive doesn't work on disable/readonly inputs, because it's only evaluated when a change in the input value causes a new value to be committed to the model. So, since you're changing the value programmatically and not typing anything to this model, it doesn't calls ngChange
Here is more one part extracted from docs:
ngChange will not be evaluated:
if the value returned from the $parsers transformation pipeline has not changed
if the input has continued to be invalid since the model will stay null
if the model is changed programmatically and not by a change to the input value
So, to achieve what you want you must move your ng-change to your <select>.
I hope it helps.

Related

Incompatibility between ng-value and ng-model [duplicate]

As far as i understood ng-model sets the value for that particular element in which the model is been assigned.
given that how is ng-value different from ng-model?
It works in conjunction with ng-model; for radios and selects, it is the value that is set to the ng-model when that item is selected. Use it as an alternative to the 'value' attribute of the element, which will always store a string value to the associated ng-model.
In the context of radio buttons, it allows you to use non-string values. For instance, if you have the radio buttons 'Yes' and 'No' (or equivalent) with values 'true' and 'false' - if you use 'value', the values stored into your ng-model will become strings. If you use 'ng-value', they will remain booleans.
In the context of a select element, however, note that the ng-value will still always be treated as a string. To set non-string values for a select, use ngOptions.
Simple Description
ng-model
Is used for two way binding of variable that can be available on scope as well as on html.
which has $modelValue(value reside in actual scope) & $viewValue (value displayed on view).
If you mentioned on form with name attribute then angular internally creates validation attributes for it like $error, $valid, $invalid etc.
Eg.
<input type="text/checkbox/radio/number/tel/email/url" ng-model="test"/>
ng-value
Is used to assign value to respective ng-model value like input,
select & textarea(same can be done by using ng-init)
ng-value does provide good binding if your are setting ng-model value through ajax while writing value attribute doesn't support it
Basically meant to use for radio & option tag while creating select options dynamically.
It can only have string value it, it doesn't support object value.
HTML
<input
[ng-value="string"]>
...
</input>
OR
<select ng-model="selected">
<option ng-value="option.value" ng-repeat="option in options">
{{option.name}}
</option>
</select>
...
A good use for ng-value in input fields is if you want to bind to a variable, but based on another variable's value. Example:
<h1>The code is {{model.code}}.</h1>
<p>Set the new code: <input type="text" ng-bind="model.code" /></p>
When the user types in the input, the value in the title will be updated. If you don't want this, you can modify to:
<input type="text" ng-value="model.code" ng-bind="model.theNewCode" />
theNewCode will be updated, but code will remain untouched.
According to the https://docs.angularjs.org/api/ng/directive/ngValue, ngValue takes an "angular expression, whose value will be bound to the value attribute of the input element".
So, when you use ng-value="hard", it is interpreted as an expression and the value is bound to $scope.hard (which is probably undefined).
ngValue is useful for evaluating expressions - it has no advantage over value for setting hard-coded values. Yet, if you want to hard-code a value with ngValue, you must enclose it in '':
ng-value="'hard'"
ng-model is intended to be put inside of form elements and has two-way data binding ($scope --> view and view --> $scope) e.g. <input ng-model="val"/>.
or you can say The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.
The documentation clearly states that ng-value should not be used when doing two-way binding with ng-model.
From the Docs:
ngValue
Binds the given expression to the value of the element.
It can also be used to achieve one-way binding of a given expression to an input element such as an input[text] or a textarea, when that element does not use ngModel.
— AngularJS ng-value Directive API Reference
Instead, initialize the value from the controller:

How to make ng-model work with ng-value?

I have this input:
<input type="number" id="totWeight" ng-model="totWeight" ng-value="getTotWeight()" />
which value is calculated based on other fields, but it can also be inserted manually via the input field.
The problem is that when it's calculated, ng-model remains empty, so I tried to assign the calculated value if (!$scope.totWeight) when I send the data to the server, which is not optimal. Further if I insert a value via the input field and then change the other fields mentioned above which trigger the getTotWeight() function, the $scope.totWeight has a value so it won't get updated with the above if (!$scope.totWeight).
Sorry, I don't know how to explain it. Hopefully someone can help me with that.
The purpose of the NgValue directive is as the docs says
It is mainly used on input[radio] and option elements, so that when
the element is selected, the ngModel of that element (or its select
parent element) is set to the bound value.
So when using input type "number" you should not use it as it's value actually will be in the NgModel instead.
If you want to trigger an event when the input is change, key is press etc you should use the NgChange, NgKeypress etc instead to trigger the function.
The value will be keept in the NgModel for all situations.

ng-change is not getting called when drop-down value remains the same

In select tag, ng-change and ng-options are used. So in the drop-down when i change the value, ng-change is getting called. if the drop-down value remains the same, it is not getting called. but I want it to happen.
sample code is below:
<select class="report-select-padding selectdwn" name="additem" ng-change="addFilter(filterItem)" style="background: #989FA9; color:#000;"
ng-model="filterItem" ng-options="column as column.columnName for column in columns">
<option style="display:none" style="background: #ffffff;" value="">Add Item</option>
</select>
ng-change need a change to trigger the function. you can use ng-click instead to call function for every click.
ng-change is programmed to work that way. The idea is to trigger the event on change. See here
It will not be evaluated:
if the value returned from the $parsers transformation pipeline has not changed
if the input has continued to be invalid since the model will stay null
if the model is changed programmatically and not by a change to the input value

ng-model preventing ng-value to be displayed

I'm pretty new to angular world and I have an issue with it.
I'm working with ejs too.
I have an input that I want to fill (value) with an ng-model.
The problem is my model is empty while the user doesn't specify a value.
I want to display a default value when my model is empty. This default value is sending by the ejs (server side). Doing that, I can't set a default value in my controller.
To do so I wrote the following :
<input type="text" ng-model="owner_adress" ng-value="'{{owner_adress || '<%=user.owner_adress%>'}}'"/>
If I look into my code, I can see the value is okay (ejs result when my model is empty, my model value otherwise) but the value is not displayed in my input (ie the user can't see it).
I looked for a work around (ng-cloak was fine but I can't use it in my input field).
Any clue would be nice !
Use ngInit directive instead. If owner_adress is defined in controller it will be used, otherwise it will default to serverside rendered value:
<input ng-model="owner_adress" type="text"
ng-init="owner_adress = owner_adress || '<%=user.owner_adress%>'"/>

AngularJS: How to show the next form field depending on validity of the previous one

I need to display the next field in my form depending on the last value selected in the form. All fields in my form are independent views, specifically are ng-include.
The idea is not to show all fields when the page loads, and instead, show the next field according to the value selected in the previous field.
Example 1:
My first input (my first ng-include) is a text field, maybe on trigger onBlur check if the value is correct and then show the next field (my second ng-include), then, if that value is correct and then show the next field (my third ng-include).
Example 2:
This time my first input (my first ng-include) is a checkbox field, maybe on trigger onBlur check if the value is correct and then show the next field (my second ng-include), then, if that value is correct and then show the next field (my third ng-include).
Thanks.
Are you familiar with ng-show?
- It shows or hide element depended on value which you declare in ng-show tag.
You can wrap each field (or a group of fields) in ng-form and show the next section depending on the validity of the form of the current section. The fact that elements of the form are delivered via ng-include has little bearing on the approach:
<div ng-form="form1">
<input ng-model="v.one" required min-length="3">
</div>
<div ng-form="form2" ng-show="form1.$valid && !form1.$pending">
<input ng-model="v.two" required min-length="3">
</div>
<div ng-form="form3" ng-show="form2.$valid && !form2.$pending">
<input ng-model="v.three" required>
</div>
This is, of course, at a high-level, and doesn't deal with cases where previous becomes invalid while the next form is showing. For those, more complicated, cases it is better to do the logic in the controller and expose the decision via a function or a scope variable, e.g. showForm2():
<div ng-form="form2" ng-show="showForm2()">
<input ng-model="v.two" required min-length="3">
</div>

Resources