Multiple ng-models on one input field? - angularjs

I have a form, and a list of items.
I used ng-model="searchFor" to filter out the list of items appropriately (this part is working fine), but I also want to "submit" the item that's filtered out -- which would require ng-model="adding_item.name" on the input field as well (I think).
Can you have multiple ng-models on one input field?
Is there another way around this?

Try using ng-change event to capture model value and assign it to other input element with its own ng-model.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<input type="text" ng-model="input" ng-change="input1=input;input2=input; " />
<input type="hidden" ng-model="input1" />
<input type="hidden" ng-model="input2" />
<br>Model
<br>{{input | uppercase}}
<br>Model 1
<br>{{input1 | uppercase}}
<br>Model 2
<br>{{input2 | uppercase}}
</div>

No, ngModel wasn't supposed to do things like this, at this point it is better to start relocating the logic from the view. For this scenario you could make use of getterSetter option:
https://docs.angularjs.org/api/ng/directive/ngModel#binding-to-a-getter-setter
It is hard to make substantial suggestions without seeing the code.

Related

Angular - Firing message onBlur after user edits field

Like others, I have been looking for a good way to validate my forms with Angular without the messages being too aggressive. The closest I have gotten is checking for $dirty and $touched prior to firing the messages. Which works for most situations.
The one situation I can't figure out is when the user edits, for example, a required field. The field has text in it, is valid, dirty, and touched. The user goes back into the field to change it. They backspace what is in the input and immediately the message fires because the input is now dirty, touched, and invalid. I'd rather it "reset" at that point and reevaluate when the user blurs the input again. Give them a chance to fill in the input while it's still focused.
Make sense? Any ideas?
Thanks!
Matt
Perhaps this works:
ng-model-options="{ updateOn: 'blur' }"
Add it to your input element. I believe the validation will occur when the model is updated, this way the model gets updated on blur.
Here you can see more options for this directive: https://docs.angularjs.org/guide/forms in Custom model update triggers. And a more detailed explanations in ngModelOptions.
Let me know if it works :)
Use function on ng-blur to validate and show messages if invalid.
ng-blur="validate()"
In your controller -
$scope.validate = function(){
//Validate logic
//If invalid
//Show message logic here
}
Take a look at the ngMessages documentation:
https://docs.angularjs.org/api/ngMessages/directive/ngMessages
You have an example there that shows you how to use it:
<form name="myForm">
<label>
Enter your name:
<input type="text"
name="myName"
ng-model="name"
ng-minlength="5"
ng-maxlength="20"
required />
</label>
<pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
<div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
<div ng-message="required">You did not enter a field</div>
<div ng-message="minlength">Your field is too short</div>
<div ng-message="maxlength">Your field is too long</div>
</div>
</form>
I think this is the best way to do it (at least it's how I do it).

How can I reference bound data within a ng-click attribute?

It's been a long day, and I am likely missing something obvious but. . .
I have a ng-repeat list of radio buttons that reflects live UPS shipping rates to a customer's location (e.g. "Overnight", "2 day", etc).
Here is the markup:
<div ng-repeat="i in ShippingRates">
<div class='radio'>
<label>
<input value="{{i.Rate}}" ng-model="Cart.ShippingCharge" type="radio" name="shipping-method" ng-click="SetSelectedMethod('Other')" />{{i.ShippingMethod}} <span ng-if="i.Rate > 0">({{i.Rate | currency}})</span></label></div>
</div>
I already have the ng-model of the radio button associated with i.Rate returned from UPS (e.g. $100).
Now, I additionally need to store the text of the radio button as the "SelectedShippingMethod". I thought the way to do this might be to add a ng-click like this:
<input value="{{i.Rate}}" ng-model="Cart.ShippingCharge" type="radio" name="shipping-method" ng-click="SetSelectedMethod('{{i.ShippingMethod}}')" />
And then the function would be something like:
$scope.SetSelectedMethod = function(method){
$scope.SelectedShippingMethod = method;
}
But this does not work as it results in $scope.SelectedShippingMethod literally getting set to "{{i.ShippingMethod}}".
Any help is appreciated.
the function inside the ng-click is already a JavaScript method, not an HTML snippet, so you don't have to evaluate the variable as an expression. Simply call the variable.
e.g. ng-click="SetSelectedMethod(i.ShippingMethod)"

How can I mimic the tags box behaviour from SO in AngularJS?

How can I mimic the tags box behaviour from SO in AngularJS? I'm trying to do something kind of similar where the user enters a set of space/comma-delimited words and as each one is typed I want to parse it out and put it into an array. I know there are probably 30 different ways to do this with bespoke javascript but I'm looking to leverage AngularJS in the most efficient way possible here.
At the moment I have an ng-model based on the input field and I'm doing an ng-repeat to create spans containing each tag, but angular uses commas as the delimiter and it also includes partially-formed words. So I only want to include words that have been delimited by the space/comma and I want to put them into an array so I can perform some validation on each one as it's entered, see below.
<form role="form" class="form-inline" data-ng-submit="updateScore()">
<input data-ng-list data-ng-model="labels" placeholder="Enter labels" class="form-control" type="text" >
</form>
<span data-ng-repeat="label in labels track by $index">
<span class="badge">
{{ label }} 5 <span class="glyphicon glyphicon-remove-sign"></span>
</span>
</span>
Any ideas?
Figured it out actually...
<input data-ng-list="/[,\s]/" data-ng-model="labels" placeholder="Enter labels" class="form-control" type="text" >

One form element updating multiple pieces of the model?

I am looking at using angular for a project at work but I have a question first. We have a single page application that's pretty intricate. We do have a basic model set up but some fields in the model are redundant. If I couldn't reduce the redundancy, what steps could I take in angular so that one form element changes two variables in the model?
I've put together a bare bones jsfiddle of what I'm hoping to do:
<div ng-app>
<input type="text" ng-model="yourName" placeholder="Enter a name here" /><br/>
<span>Hello {{yourName}}!</span><br/>
<span>Hello {{altName}}!</span>
</div>
How could I change this around so that the input would assign it's value to both yourName as well as altName? I've tried what I thought would be obvious such as comma or pipe delimiting the ng-model attribute to no avail. Is it possible?
You could set a $watch on the yourname-Variable within your controller and then change the altName in its callback. Should look like this:
$scope.$watch('yourName', function(){
$scope.altName = $scope.newName;
});

Ng-model's attribute in a ng-repeat input checkbox gets always literal or give error

So i need to know the extras of a car than a user wants to include in his preferences.
I'm trying to create input checkboxes from an array obtained by an ajax request and generate the inputs by ng-repeat. The major objective is to know the checkboxes selected by the user. I'd like that my approach to be create an auxiliar array which contains the selected ones, but i don't know how to set a unique ng-model to every item in the ng-repeat iteration so i can know the list of selected items. I guess there is something left in my knowlege of angular. Here is what i have for now..
In the controller...
$http.get('/ajax/ajax_get_extras/'+$scope.car.version+'/false').success(function(data) {
$scope.extras = data;
});
$scope.addExtra = function(){ // ... manage the auxiliar array }
In the html ...
<div ng-controller="Controller">
<form novalidate class="simple-form">
<span ng-repeat="extra in extras">
<input type="checkbox" ng-model="extra.id" ng-change="addExtra()" name="extra_{{extra.id}}" >{{extra.name}} - <strong>{{extra.real_price | onlynumber | currency}}</strong>
</span>
</form>
</div>
And i'm stuck since the extra.id doesnt transform to the real extra.id and stays as a string "extra.id" >_<
I tried extra_{{extra.id}}, extra.id, {{extra.id}}, $index as posibles ng-model and none works.
In AngularJS 1.1.5 there is "track by" that you can use in ngRepeat.
So you can:
<input type="checkbox" ng-repeat="e in extra track by $index" ng-model="extra[$index]">
Here is a example: http://plnkr.co/edit/6lNo6R5EPsNGHUU6ufTE?p=preview

Resources