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
Related
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);
};
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/
I am working on SPA and I include HTML pages into one basic page by ng-include.Let's call this basic page as external and the included pages as internal.In an internal page I have set an input attribute to be ng-model="userd.Username" and in the external page i would like to get the value of this input.
In some internal page register.html there is the following code:
<div class="form-group">
<div class="form-group">
<span class="regForm text-danger">*</span> <input
ng-model="userd.Username" type="text" maxlength="10"
placeholder="Enter your name" class="form-control input-md"
required />
</div>
<div class="form-group">
<span class="regForm text-danger">*</span> <input
ng-model="userd.Password" type="password" maxlength="8"
placeholder="Enter your password" class="form-control input-md"
required />
</div>
<div class="form-group">
<span class="regForm text-danger">*</span><input
ng-model="userd.Nickname" type="text" maxlength="20"
placeholder="Enter your nickname" class="form-control input-md"
required />
</div>
<div class="form-group">
<input ng-model="userd.Description" type="text" maxlength="50"
placeholder="Enter description about you"
class="form-control input-md" />
</div>
<div class="form-group">
<input ng-model="userd.Photo" type="text"
placeholder="Enter photo URL" class="form-control input-md" />
</div>
<div class="form-group">
<button ng-click="registerBtn()" class="btn btn-primary">Register</button>
</div>
</div>
In the external page:
<div ng-include="'register.html'" ng-controller="registerCon" ng-show="logreg"></div>
I've tried to use the $rootscope as following in the main controller of the external page:
var appvar = angular.module('myApp', []);
//The Main Controller of the page (single web page)
appvar.controller('myCtrl',['$scope','$http','$rootScope',function($scope, $http,$rootScope) {
$rootScope.storedsession="";
}]);
And in the controller 'registerCon' I wrote:
appvar.controller('registerCon',['$scope','$http','$rootScope',function($scope, $http, $rootScope) {
$scope.registerBtn = function() {
console.log(this.userd);
$http.post("http://localhost:8080/ExampleServletv3/registeruser",this.userd)
.success(function(response) {
console.log(response);
setTimeout(function () {
$scope.$apply(function(){
$rootScope.storedsession=this.userd.Username;
console.log($rootScope.storedsession);
});
});
});
};
}]);
but it prints undefined for console.log($rootScope.storedsession); in the console,I also tried $scope instead of $rootScope but it didn't work too.
Can someone help me please?
Thanks
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>
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