In some cases I need to apply different attributes to a node based on properties in my model.
For example, in one case I need to add a 'required' tag and in another case not. I've been using ng-if with different branches to accomplish this but the cases are getting out of hand quickly.
<div ng-if="model.required">
<input class="form-control"
type="text"
required
ng-model="model" />
</div>
<div ng-if="!model.required">
// as different options arise,
// i have more forks for each attribute combo
<input class="form-control"
type="text"
ng-model="model" />
</div>
Is there a better way to dynamic apply attributes to nodes?
I have quickly created a directive that allows you specify attributes dynamically.
http://jsfiddle.net/HB7LU/1806/
I'm not sure if it will have the desired effect you are after in this simple form, but it might be a good starting point. You essentially use:
<div dyn-attrs="someModelArray"></div>
And set your model accordingly:
$scope.someModelArray = [
{ attr: 'myattribute', value: '' },
{ attr: 'anotherattribute', value: 'val' }
];
In this case it would be best to make use of ngRequired:
<input class="form-control" type="text" ng-required="model.required" />
Related
I am using Bootstrap 4 to style my form controls, and want to use the Bootstrap Forms validation styles when Angular's ngModel adds CSS classes to forms, such as ng-valid, ng-invalid, ng-dirty, ng-pending.
For example, if I have the following form
<form novalidate>
<input type="email" class="form-control" ng-model="user.email" required />
</form>
and want to apply Bootstrap's .has-danger class when the control fails data validation with Angular (i.e. when ngModel adds the class .ng-invalid). How do I accomplish this or something to the effect of
input.ng-invalid {
/* inherit from bootstrap's
.form-control-danger */
}
I would use ng-class for applying the bootstrap classes. Bootstrap defines the styling of the classes once applied.
<form name='myForm'>
<input type="email" name='input' class="form-control" ng-model="user.email" ng-class="myForm.input.$valid ? '' : 'has-danger' " required />
//or get fancy with the object argument form of ng-class
... ng-minlength='3' ng-class="{
has-success: myForm.input.$valid,
has-warning: myForm.input.$error.minlength,
has-error: myForm.input.$error.required}"
Checkout: https://docs.angularjs.org/api/ng/directive/form
In Angular2 you can use the same approach as the #Tyler answer but with the new syntax.
<div
class="form-group"
[ngClass]="{ 'has-success': user.valid, 'has-error': user.invalid}"
>
<input
type="text"
class="form-control"
id="usr"
name="usr"
required
#user="ngModel"
[(ngModel)]="model.usr"
>
</div>
You create a new variable named user, line #user="ngModel", which contains the model state for user input. And with [ngClass]="{ 'class-name': bool-expression}" you assign classes when they expressions become true.
Have in mind that you need to put the classes names as strings if they aren't a valid JavaScript identifier (they have an - for example).
I am generating a dynamically text boxes using angularjs. I set a array in controller and repeating in view with ng-repeat. Here is controller code :-
this.total_options = [
{text : 'form.options.Option1' , placeholder: 'Enter Option Here'},
{text: 'form.options.Option2', placeholder: 'Enter Option Here' }
];
Now in view i am repeating this options like :-
<li data-ng-repeat="option in mcssController.total_options">
<input required="required" type="text" ng-model="option.text" class="option" placeholder="{{option.placeholder}}" />
</li>
But when page is rendered the textbox showing ng-model property 'form.options.optoin1' instead of placeholder('Enter Option Here'). How can i solve this problem ?
See if you clear out the form, you should be able to see the placeholder!
Try:
<li data-ng-repeat="option in mcssController.total_options">
<input required="required" type="text" ng-init="model=$eval(option.text)" ng-model="model" class="option" placeholder="{{option.placeholder}}" />
</li>
You want ngModel to bind to a model, not a property that represents a string. Since you want to interpret the string as a model, you can use $scope.$eval. It should work if you use $scope.$eval in an ngInit expression, and then use result to bind to ngModel.
My application has a lot of models in the page. I want to detect whether user has changed value of any model on click of save. Using $watch on every model puts too much load, so don't want to use this method. Is there any good approach for this?
Small snippet is like below:
<div>
<div class="ttere2">
<input type="radio" name="nc2-radio3" ng-model="nc2PenaltyAfter" value="specificDays" />
<input class="ggfe1" ng-model="nc2AfterDays" ng-disabled="nc2PenaltyAfter!='specificDays'" type="number" min="1" max="100" step="1" value="1" />days</div>
<div class="admin_wp-line">
<input type="radio" name="nc2-radio3" ng-model="nc2PenaltyAfter" value="immediately"/> Immediately </div>
<div class="acfv1">model 1</div>
</div>
<div style="margin-top: 20px;"><button ng-click="saveData();">Done</button></div>
............too many inputs go here
</div>
Use .$dirty! Angular will set this on every element that is bound using ng-model, automatically, when it has been changed. It will also set it on the entire form. You can access it in code like this:
if ($scope.myForm.$dirty) {
// Your code here
}
Angular will provide six useful variables on the form, and every ngModel-bound element in your form: $dirty and $pristine, $valid and $invalid, and $touched and $untouched. You can mix and match these to drive a lot of useful behaviors, and they're available both in your controller (using the expression shown above) and your template (directly).
Here is the Plunker that describe my problem with dynamic binding in Angularjs.
http://plnkr.co/edit/fGgtOZ5IrJVo9QasQALc?p=preview
Before using Angularjs, I am used to using the input name/value like the following to generate desirable data structure for back end processing
<input type="text" name="computer[details][][purchaseddate]" />
<input type="text" name="computer[details][][warrantyperiod]" />
With Angularjs ng-model, it is possible to bind a complex data structure like
<input type="text" ng-model="computer.parts[0].name" />
However it does not work with dynamic property like the following:
<input type="text" ng-model="computer.details[0].name" />
Angular keeps telling me that I am trying to set property 'name' to undefined 'details[0]', I am aware of that but are there any ways to get the same behavior with previous input's name/value where I can specify dynamic property without having to declare it first?
Thank you,
Binding to attributes that don't exist yet works. You can bind to a.b.c even if $scope.a does not exists. Angular creates the objects and attributes on-the-fly.
<input type="text" ng-model="a.b.c" />
But you are trying to bind to an array element that does not exist yet:
<input type="text" ng-model="a.b[0].c" />
Angular would have instantiate the array and then push an empty object in it and then assign it's name. Apparently this does not work.
I ran into the same situation and tried everything.
This is how I was able to get dynamic values inside 2 deep ng-repeat:
JS:
$scope.newContact = {
name: [],
phone: [],
email: [],
notes: []
};
$scope.saveNewContact = function (idx) {
console.log($scope.newContact.name[idx]);
};
HTML:
<input type="text" ng-model="newContact.name[$index]" />
<input type="text" ng-model="newContact.phone[$index]" />
<input type="text" ng-model="newContact.email[$index]" />
<input type="text" ng-model="newContact.notes[$index]" />
<button ng-click="saveNewContact($index)">Save</button>
Is there anyway that I can bind two model values to one input field?
Suppose I have input field which I want to be the value of two variables in the scope something like:
<input type="text" model="sn_number; id" >
You cannot, but there are some workarounds.
1. Use ngChange to update the other model
<input type="text"
ng-model="sn_number"
ng-change="id=sn_number"/>
2. You could watch a model, and when in changes, update another
$scope.$watch('sn_number', function(v){
$scope.id = v;
});
You would need to watch also for changes in id if you want to keep them in sync.
Example here
You can bind fields immediately, not only in ng-change, and actually it isn't data binding, its only angular expression
<label>Name</label>
<input type="text" ng-model="name" value="{{name}}"/>
<label>Key</label>
<input type="text" ng-model="key" value="{{key=name}}" />
It would make no sense to bind an input to two variables in the model. Binding works both ways, so if the model is updated, the field is updated and vice-versa. If you were to bind to two variables, what would be the single source of truth?
However you can use ng-change to call a method on the controller which can set two variables when the field changes.
with ng-init
<div ng-controller="ctrl" ng-init="model = { year: '2013', month:'09'}">
or
<div ng-repeat="c in contact" ng-init="likes = { food: 'steak', drink:'coke'}">