AngularJS ng-repeat for input array - angularjs

I have empty model with cars:
$scope.registration.cars = {
1: {
capacity: '',
count: '',
license: ''
},
2: {
capacity: '',
count: '',
license: ''
}
};
Then I use ng-repeat to generate cars form:
<div class="row row_vehicles" ng-repeat="(key, value) in registration.cars">
<input type="number" name="registration_car_capacity[{{key}}]" ng-model="registration.car[{{key}}].capacity" />
<input type="number" name="registration_car_count[{{key}}]" ng-model="registration.car[{{key}}].count" required />
<input type="text" name="registration_car_license[{{key}}]" ng-model="registration.car[1].license" ng-minlength="7" required />
</div>
But this is not working. How can I insert KEY into ng-model array?

Don't use interpolation operator ({{..}}) inside angular scope.(anything like ng-*), In your case ng-model
<div class="row row_vehicles" ng-repeat="(key, value) in registration.cars">
<input type="number" name="registration_car_capacity[key]" ng-model="registration.car[key].capacity" />
<input type="number" name="registration_car_count[key]" ng-model="registration.car[key].count" required />
<input type="text" name="registration_car_license[key]" ng-model="registration.car[key].license" ng-minlength="7" required />
</div>

You just have to remove interpolation {{}} enclosing the key. You can't use this with angular directives.
<div ng-controller="MyCtrl">
<div class="row row_vehicles" ng-repeat="(key, value) in registration.cars">
<input type="number" name="registration_car_capacity[key]"
ng-model="registration.cars[key].capacity"
/>
<input type="number" name="registration_car_count[key]"
ng-model="registration.cars[key].count"
required />
<input type="text" name="registration_car_license[key]"
ng-model="registration.cars[key].license"
ng-minlength="7" required />
</div>
</div>
Working Fiddle: http://jsfiddle.net/ADukg/12094/

Related

angular 1.x array push with multiple variables via html form

I would like to push text via a html form in my array. The problem is that every tutorial I habe seen only explains how I add one variable.
My Array:
(this is that I mean)
$scope.titles = [{
title: 'New Divide',
artist: 'Linkin Park',
album: 'New Divide',
genre: 'Rock',
cover: 'new-divide.jpg',
titleLength: '4:28',
file: 'test'
}];
My html form:
<form ng-submit="musicController.addMusic(musicController.titles, musicController.artist, musicController.album, musicController.genre, musicController.titleLength, musicController.cover, musicController.file)">
<input ng-model="musicController.title" type="text" />
<input ng-model="musicController.artist" type="text" />
<input ng-model="musicController.album" type="text" />
<input ng-model="musicController.genre" type="text" />
<input ng-model="musicController.titleLength" type="text" />
<input ng-model="musicController.cover" type="text" />
<input ng-model="musicController.file" type="text" />
<button type="submit" class="btn btn-primary">Add</button>
</form>
You should define the ng-model for each of your inputs as an object property. That way they will all be grouped together in one object so you won't have to push each individual value:
<form ng-submit="musicController.addMusic(musicController.record)">
<input ng-model="musicController.record.title" type="text" />
<input ng-model="musicController.record.artist" type="text" />
<input ng-model="musicController.record.album" type="text" />
<input ng-model="musicController.record.genre" type="text" />
<input ng-model="musicController.record.titleLength" type="text" />
<input ng-model="musicController.record.cover" type="text" />
<input ng-model="musicController.record.file" type="text" />
<button type="submit" class="btn btn-primary">Add</button>
</form>
Just to clarify, your addMusic function should look something like the following:
$scope.addMusic = function(record) {
$scope.titles.push(record);
};

Create a dynamic ng-model for an input

How can I make the ng-model of an input dynamic?
Static ng-model:
<input type="text" ng-model="myModel.firstName" />
Dynamic ng-model:
$scope.myInputs = [{ key: "firstName"}, { key: "lastName" }];
<div ng-repeat="input in myInputs">
<input type="text" ng-model="myModel[input.key]" />
</div>
The myModel[input.key] does not seem to be calculating correctly.
In myInputs[input.key], input.key is not the index. So you cannot access expected value.
You can either
<div ng-repeat="input in myInputs">
<input type="text" ng-model="input.key" />
</div>
Or
<div ng-repeat="input in myInputs track by $index">
<input type="text" ng-model="myInputs[$index].key" />
</div>

AngularJS ngDisabled isn't activated as it should be

I have a code that should disable a button when : registerForm.$invalid || form.password != form.passwordBis, which should mean : "Disable the button if the form isn't valid OR if the '$scope.form.password' variable isn't equal to '$scope.form.passwordBis'.", isn't it?
So here I have a code that activate the button if the two passwords matches. Which shouldn't happen, because the first condition is still wrong !
HTML :
<div ng-app="app" ng-controller="formCtrl">
<form name="registerForm">
<div class="header">
<h2>Create your account</h2>
</div>
<div class="form-group">
<div class="title">First Name</div>
<input type="text" name="firstName" ng-required class="form-control" ng-class="{empty:form.firstName.length==0}" ng-model="form.firstName" required></input>
</div>
<div class="form-group">
<div class="title">Last Name</div>
<input type="text" name="lastName" ng-required class="form-control" ng-class="{empty:form.lastName.length==0}" ng-model="form.lastName" required></input>
</div>
<div class="form-group">
<div class="title">Email</div>
<input type="email" name="email" ng-required class="form-control" ng-class="{empty:form.email.length==0}" ng-model="form.email" required></input>
</div>
<div class="form-group">
<div class="title">Password</div>
<input type="password" name="password" class="form-control" ng-class="{empty:form.password.length==0}" ng-model="form.password" required></input>
<input type="password" name="passwordBis" class="form-control" ng-class="{empty:form.passwordBis.length==0}" ng-model="form.passwordBis" minlength="6" required></input>
</div>
<div ng-if="form.password != form.passwordBis" class="error">Passwords doesn't match.</div>
<div class="form-group">
<button class="btn btn-success" ng-click="register()" ng-disabled="registerForm.$invalid || form.password != form.passwordBis">Register</button><br/>
</div>
</form>
</div>
JS :
var app = angular.module("app", []);
app.controller("formCtrl", function($scope) {
$scope.form = {
firstName: "",
lastName: "",
email: "",
password: "",
passwordBis: ""
};
});
And you can test it : JSFiddle
What am I missing ?
Remove ng-required attributes from your form elements.
For form elements you should use either ng-required or required, but not both at the same time. ng-required expects an expression that needs to evaluate to true in order to mark a form element as required, whereas required doesn't need any value. See https://stackoverflow.com/a/16648851/1237995 for more detailed explanation.

$scope.formName.fieldName.$setValidity is not working

I would like to set invalid with angular when firstname is equals to lastname and change the color using styles to red.
http://jsbin.com/japir/2
function RegoController($scope) {
$scope.app = {
firstName: "Saroj"
};
$scope.$watch("app.lastName", function(newVal, oldVal) {
if (!!$scope.app.lastName && !!newVal)
if (angular.lowercase($scope.app.firstName) === angular.lowercase(newVal)) {
debugger;
$scope.form.inputLastName.$setValidity("sameName", false);
}
});
}
<body ng-app>
<div class="container" ng-controller="RegoController">
<div class="col-lg-4">
<form name="form">
<div class="form-group">
<label for="inputFirstName">First Name</label>
<input id="inputFirstName" class="form-control" type="text" ng-model="app.firstName" placeholder="Enter your firstname" required ng-minlength="3" ng-maxlength="20" />
</div>
<div class="form-group">
<label for="inputLastName">Last Name</label>
<input id="inputLastName" class="form-control" type="text" ng-model="app.lastName" placeholder="Enter your last name" required ng-minlength="3" ng-maxlength="20" />
</div>
<div class="form-group">
<label for="inputEmail">Email</label>
<input id="inputEmail" class="form-control" type="email" ng-model="app.email" placeholder="Enter your email" required />
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Save" />
</div>
</form>
{{app}}
</div>
</div>
</body>
The problem is that you are trying to select a form input that has no name; thus making it unable to find the field you are trying to invalidate. Here is a working example:
JSBIN: http://jsbin.com/yozanado/1/
Input field with name:
<input id="inputLastName" name="lastName" class="form-control" type="text" ng-model="app.lastName" placeholder="Enter your last name" required ng-minlength="3" ng-maxlength="20" />
Javascript:
$scope.form.lastName.$setValidity("sameName", false);
AngularJS form validation relies on the name of the form and the name of the fields to find the validation models on scope.
For example, if your HTML is:
<form name="form">
<input name="firstName" ng-model="firstName" />
</form>
You will be able to access the validation $error property on scope using the name attributes:
$scope.form.firstName.$error.sameName
To fix the issues you're having, add a name attribute to your input fields.
JSBin Demo

Bind <div> to element of Angular controller

We have a somewhat complicated model on an AngularJS controller:
function controller($scope) {
$scope.model = {
childmodel1: {
childmodel2: {
property1: 'abc',
property2: 3,
property3: 0.5,
property4: 'abc'
}
}
}
}
In the HTML markup, we don't want to repeat the whole access chain everytime we access childmodel2:
<div ng-controller="ctrl">
<div>
<input type="text" ng-model="model.childmodel1.childmodel2.property1" />
<input type="text" ng-model="model.childmodel1.childmodel2.property2" />
<input type="text" ng-model="model.childmodel1.childmodel2.property3" />
<input type="text" ng-model="model.childmodel1.childmodel2.property4" />
</div>
</div>
Is there an AngularJS directive that creates a sub-scope like this:
<div ng-controller="ctrl">
<div ng-unknowndirective="model.childmodel1.childmodel2">
<input type="text" ng-model="property1" />
<input type="text" ng-model="property2" />
<input type="text" ng-model="property3" />
<input type="text" ng-model="property4" />
</div>
</div>
It's the same thing that's done on ng-repeat, but without the repetition :)
We tried ng-scope, ng-controller, ng-model, none of them works this way. Googling didn't yield any results, we don't know the terminology to search for.
Thank you #Ufuk, here's my solution:
mt.directive('subscope', function () {
return {
scope: {
subscope: '='
}
};
});
and
<div ng-controller="ctrl">
<div subscope="model.childmodel1.childmodel2">
<input type="text" ng-model="subscope.property1" />
<input type="text" ng-model="subscope.property2" />
<input type="text" ng-model="subscope.property3" />
<input type="text" ng-model="subscope.property4" />
</div>
</div>
You can use ng-init to suppress the access chain
<div ng-init="childmodel2 = model.childmodel1.childmodel2">
<input type="text" ng-model="childmodel2.property1" />
<input type="text" ng-model="childmodel2.property2" />
<input type="text" ng-model="childmodel2.property3" />
<input type="text" ng-model="childmodel2.property4" />
</div>
It creates alias model. More appropriate you create the alias in your controller like
$scope.childmodel2 = $scope.model.childmodel1.childmodel2 // and remove ng-init from HTML
Demo

Resources