In angular require a field only if it's not disabled - javascript

How can I require a field only if it's not disabled? This didn't work:
<form name="foo">
<input type="text" name="bar" ng-required="!foo.bar.disabled">
</form>
Note that I am disabling the field directly through pure javascript, not with ng-disabled. I have a directive that runs through the form enabling/disabling things.
The directive listens to $on messages, and depending on what is gets will run:
element.find(':input').prop('disabled', true);
The $on messages come from a different scope, so I can't directly reference it and do ng-disabled=.....

Use ng-disabled with a scope variable. Your directive can then enable/disable the input through this scope variable. If your directive inherits from another scope, please use an intermediate factory to manage the scope variable.
$scope.barDisabled = dataSharer.barDisabled;
In above example the dataSharer is a factory and barDisabled directs to singleton.
In your form:
<form name="foo">
<input type="text" name="bar" ng-required="!bartDisabled" ng-disabled="barDisabled">
</form>

Related

Angular form validation with external data binding

I have an Angular 4 form, but with the data tracked in an injected service (for reasons outside the scope of this question).
Each input looks something like...
<input name="..." [ngModel]='getVal(...)' (ngModelChange)='setVal(...)'>
...because there's extra functionality in those getters/setters.
That's working great, but I would also like to use the built-in validation. If I give my form a template reference variable...
<form id="..." #myForm="ngForm">
and look at the value of myForm, it's not tracking any of those inputs. I get that, I mean, I'm specifically telling it to track them elsewhere.
But how can I take advantage of the built in HTML5 validation? i.e. required and pattern
You can use validation like this in your html. This is template based validation as per your requirement.
Submit button will not be active till all the fields are validated.
<form (ngSubmit)="submitFunc()">
<input name="name" [ngModel]='getVal(...)' (ngModelChange)='setVal(...)'
required pattern=""> //required pattern here
<button [disabled]="!myForm.form.valid" type="submit">Submit Form </button>
</form>
You have to add required in your input field and specify pattern with a regular exression.

Angular populate input fields

I have a object that gets populated via a restful API in my root scope and then in my child scope I'm trying to populate some input fields.
child controller
$scope.profileForm = $scope.$parent.student;
this works and I can
console.log($scope.profileForm.FirstName);
but the input on my page does not populate?
<input ng-model="profileForm.FirstName" type="text" class="form-control form-control-first" id="first-name-input" placeholder="FIRSTNAME" required />
Any help would be great :)
Fixed! :) i Had
<form name="profileForm" ... />
which messes up the scope variable, duh!

What should we use for assigning model data in Angular JS?

I would like to know the better way of assigning model name for each form elements using Angular JS.
I can assign it using individual scope variables.
<input type="text" ng-model="firstName"/>
<input type="text" ng-model="lastName"/>
I can also assign it using singleton object.
<input type="text" ng-model="contact.firstName"/>
<input type="text" ng-model="contact.lastName"/>
Which is the better way of handling form data in terms of memory and execution time?
You should choose the second option, in order to avoid issue with scope inheritance, see the doc:
Scope inheritance is normally straightforward, and you often don't even need to know it is happening... until you try 2-way data binding (i.e., form elements, ng-model) to a primitive (e.g., number, string, boolean) defined on the parent scope from inside the child scope.
According to Miško Hevery, the creator of AngularJS:
Whenever you have ng-model there’s gotta be a dot in there somewhere.
If you don’t have a dot, you’re doing it wrong.
The question is why?
Because ng-switch, ng-repeat, etc. creates their own scopes.
For example, have a look at this plnkr
<form ng-submit='addName()'>
Name 1: <input type='text' ng-model='name'/>
<input type='submit' value="Submit"/>
</form>
<p ng-switch='true'>
Name 2: <input type='text' ng-switch-when="true" ng-model='name'/>
</p>
<p>
Name 3: <input type='text' ng-model='name'/>
</p>
Output:
When you type in the Name 1 text box, the value shows up immediately in all text boxes. This is as expected. The problem is that now when you type into the Name 2 text box, it value gets disconnected and the three box values are no longer in sync. This is because of the way that JavaScript’s prototypal inheritance works.
To avoid, we should use dot in ng-model. For example, have a look at this plnkr
<form ng-submit='addName()'>
Name 1: <input type='text' ng-model='contact.name'/>
<input type='submit' value="Submit"/>
</form>
<p ng-switch='true'>
Name 2: <input type='text' ng-switch-when="true" ng-model='contact.name'/>
</p>
<p>
Name 3: <input type='text' ng-model='contact.name'/>
</p>
Output:
Now the code works with all three text box always in sync.
Source:
AngularJS MTV Meetup: Best Practices (2012/12/11)
5 AngularJS Antipatterns & Pitfalls
Why ng-model value should contain a dot
Nested Scopes in AngularJS
AngularJS: dot in ng-model
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
Does my ng-model really need to have a dot to avoid child $scope problems?
AngularJS: If you are not using a .(dot) in your models you are doing it wrong?

Angular - Adding an input's value with a number from $scope

I have the following code:
<div data-ng-controller="MainController">
<input class="amount" type="text" name="" value="" />
<input class="result" type="text" name="" value=""/>
</div>
I want to take a numerical value from $scope and add it to a number entered by a user in the input with class "amount" and display the result in the input with class "result". So, basically, the variable is defined in the MainController function as the following:
$scope.cost = 100;
I'm a bit confused as to what the best way is to do this, I see there are ng-value and ng-model directives at my disposal but I am having a hard time understanding which is the right one for this application (and how to properly use them).
Seems like your application is asking for an inputs and they are going to submit there values OR gonna store it somewhere in DB. So ng-model (two way binding) will suits you application, which will update the value on model & view both.
Markup
<div data-ng-controller="MainController">
<input class="amount" type="text" ng-model="cost"/>
</div>
Above field will pre-populated as 100 and as you update it will also change $scope.cost value and the value if it is displayed on view anywhere.
Don't think about the ng-value that is only one way sort of binding. You can assign the value to input using ng-value="cost" that will only update the value attribute of input but when you update input from html you will never get those changes reflected inside cost scope variable as ng-value is meant for single way binding. Thinks like you should use use ng-value only when you want to display a value.
you should use ng-model
ng-value : Its a directive useful for evaluating expression and the value is bound to $scope used for evaluating expressions
ng-model : helps in two-way data binding ,view-->controller and vice versa moreover its a directive binds the value of HTML controls

AngularJS validation, binding, etc. not working when using jQuery plugins (eg. autoNumeric)

I have an angular form which was using angular's built-in validation successfully. Take the following markup for example:
<form name="numberForm" novalidate>
<input type="text" required />
<button type="submit">Submit</button>
</form>
When the browser loads, the input field renders like this (unnecessary attributes removed):
<input class="ng-pristine ng-invalid ng-invalid-required" />
If I were to enter a value in the input field, the markup turns into:
<input class="ng-dirty ng-valid ng-valid-required" />
All of this was working great. Then I implemented two jQuery plugins to implement some masking/input formatting for the form: autoNumeric and jQuery.maskedinput. Now, nothing I do will change the original ng-pristine ng-invalid... classes on the input. It also doesn't seem to allow the binding of models to be successful either.
Any ideas?
I tried creating a http://jsfiddle.net/ma44H/3/, but can't seem to figure out how to get it to work.
JQuery and Angular do not cooperate well
Chocolate and Peanut Butter taste great together, but AngularJS and JQuery are a painful mix. We've all tried (with varying success) to accomplish this.
The problem is that JQuery DOM manipulation works outside of AngularJS Digest Cycle. The lesson is usually that using pure Angular is better.
Alternative #1: Angular UI
Try Angular-UI. Set of tools every Angular Developer could use.
Whatever Mask you want to implement can be done with their ui-mask directive:
Want a Date Mask?
<input type="text" ng-model="date" ui-mask="99/99/9999" />
Currency Mask?
<input type="text" ng-model="currency" ui-mask="$99999999.99" />
Phone Mask?
<input type="text" ng-model="phone" ui-mask="1 (999) 999-9999" />
:
See Fiddle
:
Alternative #2: Filters
Angular has built-in filters:
Currency:
$filter('currency')(amount, symbol)
Date:
$filter('date')(date, format)
Insist on using JQuery? Try the jQuery Passthrough directive from the angular-ui toolset. I haven't made use of this directive but it's an intriguing option:
To call something like $.fn.tooltip() simply do ui-jq="tooltip". Note
that the name of the function must be identical. This also works for
normal jQuery commands such as $.fn.slideUp().
To pass parameters use the ui-options attribute. The value will be
evaluated in the $scope context and passed to the function. If
defaults are set, the passed options will extend them. If a string is
passed, the default options will be ignored.
Use the directive name jq for namespacing inside uiJqConfig. Then
sub-namespace options for each function by the name of that function
(exactly as it is passed to ui-jq) so that you don't have to pass
options every time you call the directive.

Categories