AngularJS ng-model value not initially displayed in input field - angularjs

I am trying to use ng-repeat to iterate through an array of keys and display the scenario value associated with each key. The view code worked when the key value was hardcoded. Now that ng-repeat provides the key, the input field does not initially display the associated scenario value. I am using AngularJS 1.2.21.
This is the controller code that sets up $scope:
$scope.keys = KEYS; // array of strings
$scope.scenario = scenario; // object containing key: value pairs
This is the view code that generates the input:
<form name="gameSettingsForm" novalidate ng-submit="validateAndSaveSettings()" class="form-horizontal" role="form">
<div class="row">
<div class="col-md-6">
<div class="form-group" ng-repeat="key in keys">
<div class="col-md-3">
<input type="number" required ng-disabled="readOnly" class="form-control"
ng-model="scenario[key]"
id='{{key}}' name='{{key}}'>
<p>input contains {{scenario[key]}}</p>
</div>
</div>
</div>
</div>
</form>
When the page loads, the input field is empty even though the "input contains" text correctly displays the scenario[key] value. How do I get the value to display in the input field when the page loads?
UPDATE:
I had commented out all but one of the KEY array items. After activating them, most of the generated input fields are empty when the page loads. However some of them populate when the page loads. All the "input contains" strings always correctly display their scenario[key] values.
WORK AROUND:
Realized the scenario values that were displayed had been modified via multiplication. Made the problem go away by multiplying all scenario values by 1 before displaying.

The solution is to make sure the model values are numbers for inputs with type "number". I did this via multiplication:
value = value * 1;
I created a stand alone example that demonstrates the issue occurs when model values are not numbers: http://plnkr.co/qnFHafmIOWVW6eWkQsmk

Related

Angular Form Array and How to Display Error message

I have a form on which a user can dynamically add multiple input boxes for a user to add an email address.
On saving of the form, I am iterating through the list of controls, build up a JSON object and call an API to check in the DB to see if the email(s) address already exists.
If it exists, I would like to display an error message below the input indicating such .ie "email already in use".
I have a form array:
ts code
this.inviteForm = this.formBuilder.group({
invites: this.formBuilder.array([]),
alreadyUsedList: this.formBuilder.array([])
});
html
<div formArrayName="invites">
<div *ngFor="let unit of inviteForm.controls.invites.controls; let i=index" class="form-group">
<!-- The repeated alias template -->
<div [formGroupName]="i">
<input placeholder="" [type]="email" formControlName="invite" required/>
</div>
<div *ngIf="inviteForm.controls.alreadyUsedList.controls[i].controls.inUse.value == 'true'">
<div class="email-in-use">Email already in use</div>
</div>
</div>
</div>
In API response method I am attempting to set the value based on result array.
this.inviteForm.controls.alreadyUsedList.value[0].inUse = resData.Data.EmailCheck[0].AlreadyInUse
Dynamic add of email works.
API call works.
Response from API comes as expected.
PROBLEM:
Setting the value of the inUse assigns the value, however is does not result in the "Email already in use" ngIf condition being update and hence not displaying.
Any help would be appreciated.
SOLVED:
Everything was working as it should I was just not accessing the value in the array correctly in order to setValue.
this.inviteForm.controls.alreadyUsedList['controls'[0].controls['inUse'].setValue('true');
Thank you!
SOLVED:
Everything was working as it should I was just not accessing the value in the array correctly in order to setValue.
this.inviteForm.controls.alreadyUsedList['controls'[0].controls['inUse'].setValue('true');

How to use ng-show on a form button with custom repeating validators

I have a fiddle here:
https://jsfiddle.net/ntsim/41jfu7t9/
I have an ng application that uses an ng-repeat to display an array of monetary values. These values must be of the form n.nn (a positive floating pt number with two decimal places) or n (a positive integer).
Each repeating input box has a pattern test which sets an error flag (myform.texter.$error.pattern), so if this pattern is present I can show an error message next to the input box that has the error. That all works
At the end of the form I have an “Add” button that I will use to add these numbers. The add button Is always shown now, but i only want this button to appear if all the text boxes contain valid patterns, something like:
<button ng-show=“myform….”>Add<button>
But I cant get this to show/hide to work on the add button. How can I do this in angular with the show/hide?
The code for my template is shown below:
<div ng-repeat="price in prices">
<form name="myForm" class="form-horizontal" novalidate>
<input type="text" name="texter" ng-model="price" ng-pattern="monetaryRegex" \>
<span ng-show="myForm.texter.$error.pattern">
Invalid (use 5 or 5.00 for example)!</span>
</form>
</div>
<br>
<button ng-hide="myform.texter.$error.pattern">
<!-- would like to use ng-hide=xxx so that this button does not appear if any numbers are invalid-->
Add
</button>
My Controller is:
app.controller('MainCtrl', function($scope) {
$scope.instructions = 'Change these price amounts (each must be a fixed 2 decimal number or an integer) then click Add';
$scope.prices = [0.32, 12, 45.34, 45];
$scope.monetaryRegex = /^(([1-9]\d*)?\d)(\.\d\d)?$/;
});
The simplest way to do this is to take advantage of form's nesting. So basically you can do this:
<form name="outerForm">
<div ng-repeat="...">
<ng-form name="innerForm"></form>
</div>
</form>
<button ng-hide="outerForm.$error.pattern">Add</button>
Here's a working copy of your example. That being said, please check the pattern regex. I'm not by any means expert in regexes, but as yours was not working for me, I swapped it for a simple greedy ^[0-9]*\.[0-9][0-9]$.
Edit: In order your validation messages to work, for the inner form use ng-form instead of form. Example updated, cheers.

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>

Monitor specific fields for pristine/dirty form state

I'm trying to make a form that can contain complex "fieldtypes". ie. A group of fields that work together to manipulate the value of a single field.
Each of these fieldtypes contains a single field that will hold the actual "value" of the field.
The fields containing the real data will have ng-model="" attributes attached to them. The PublishController will be monitoring these fields. If there are fields without an ng-model on them, it doesn't care about it.
Is it possible to make a form only consider itself dirty/pristine by the fields with ng-model on them?
I don't mind having to put a class/attribute on all the fields I want it to watch specifically, if thats an option.
Here's an example of the code:
<div ng-controller="PublishController">
<form name="publishForm" ng-submit="save()">
<div class="fieldtype">
<!-- there might be a bunch of form elements in here that a user can manipulate to alter the value that the PublishController is concerned with -->
<input class="helper-field-1" />
<input class="helper-field-2" />
<!-- then the inputs above will perform their own logic, and output their value to this field, which the form *is* concerned with -->
<input type="hidden" name="myfield" ng-model="data.myfield" />
</div>
<div class="fieldtype">...</div>
<div class="fieldtype">...</div>
<!-- one of the goals of this is to only show the submit button when the *actual* values have been modified, not the helper fields -->
<button ng-disabled="publishForm.$pristine">Save</button>
</form>
</div>
Is what I'm describing possible?
Thanks!

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