ng-model in ng-repeat become undefined - javascript

Using Javascript with angularJs, I kind the following code :
JS
$scope.myObj = {
'sthg': '',
'a': [{
'b' : ''
}]
}
HTML
<p ng-repeat="radio in fiche.radios">
<input type="text" ng-model="radio.code" placeholder="Numéro de cliché" ng-required="true" />
<span >
<button type="button"ng-click="removeRadioList($index);" ng-disabled="fiche.radios.length === 1">
<i>X</i>
</button>
</span>
</p>
http://plnkr.co/edit/LOgk7Nudse0srS7Bs1G6?p=preview
In my App $scope.myObj.a[0].b is undefined with the ng-repeat (if I remove ng-repeat, it will be defined).
In the plunkr it is defined even after the run of ng-repeat, but I managed to have the behaviour when I enter something in the input and then delete it.
I don't get what's hapening, I would like to understand why and if it is a good way to do ?

Beacause you set ng-required="true" on your input tag angular wouldn't bind empty value to your model thous when you delete value from input your console shows you radios.code as undefined.
Please see below for working demo:
(function() {
"use strict";
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $log) {
$scope.ficheInit = {
'user_id': '',
'radios': [{
'code': ''
}]
};
$log.log($scope.ficheInit);
$scope.fiche = angular.copy($scope.ficheInit);
$log.log($scope.fiche);
$scope.addRadioList = function() {
$scope.fiche.radios.push({
'code': ''
});
}
$scope.removeRadioList = function(i) {
$scope.fiche.radios.splice(i, 1);
}
$scope.disableAddRadio = function() {
console.log($scope.fiche.radios);
return !(angular.isDefined($scope.fiche.radios[$scope.fiche.radios.length - 1].code) || $scope.fiche.radios.length < 1);
}
});
}());
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="plunker">
<div ng-controller="MainCtrl">
<button ng-click="showForm=true;">SHOW</button>
<div ng-show="showForm">
<button ng-click="addRadioList();" ng-disabled="disableAddRadio()">Ajouter un cliché</button>
<p ng-repeat="radio in fiche.radios">
<input type="text" ng-model="radio.code" placeholder="Numéro de cliché" />
<span>
<button type="button" ng-click="removeRadioList($index);" ng-disabled="fiche.radios.length === 1">
<i>X</i>
</button>
</span>
</p>
</div>
{{fiche.radios}}
</div>
</div>

Related

Why does this ng-maxlength set my valid inputs as undefined?

I am trying to add maxlength validation to my form fields, but when I add it in, it says that any length is invalid and always sets my $scope variables to 'undefined'.
Check it out here: http://jsfiddle.net/stevenr4/41L26apv/
Javascript:
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.data = {
'person1': {
'firstname': "Steve",
'lastname': "Rogers",
'maxlength': 5
},
'person2': {
'firstname': "Bob",
'lastname': "Ross",
'maxlength': 10
}
};
$scope.pkeys = ['person1', 'person2'];
$scope.log = function() {
console.log($scope.data);
}
}
HTML:
<div ng-controller="MyCtrl">
Hello, {{name}}!<br>
Sir, {{data.person1.firstname}} {{data.person1.lastname}}!<br>
and, {{data.person2.firstname}} {{data.person2.lastname}}!<br>
<div ng-repeat="key in pkeys track by $index">
{{key}}<br>
<input type="text" ng-model="data[key].firstname" ng-maxlength="data[key].maxlength"><br>
<input type="text" ng-model="data[key].lastname" ng-maxlength="data[key].maxlength"><br>
</div>
<button ng-click="log()">
Log the data
</button>
</div>
Can someone help me fix this or at least explain this to me?
Try this => ng-maxlength="{{..}}"
<div ng-controller="MyCtrl">
Hello, {{name}}!<br>
Sir, {{data.person1.firstname}} {{data.person1.lastname}}!<br>
and, {{data.person2.firstname}} {{data.person2.lastname}}!<br>
<div ng-repeat="key in pkeys track by $index">
{{key}}<br>
<input type="text" ng-model="data[key].firstname" ng-maxlength="{{data[key].maxlength}}"><br>
<input type="text" ng-model="data[key].lastname" ng-maxlength="{{data[key].maxlength}}"><br>
</div>
<button ng-click="log()">
Log the data
</button>
</div>

checkboxes are not displayed inside ng repeat angularjs

I want to display checkboxes inside ng repeat. The checkboxes are not displayed. The checkboxes are not displayed at all. I am not understanding what the misatke is. Here is the code -
<div class = "col s4">
<form ng-submit="$ctrl.todoAdd()">
<input type="text" ng-model="$ctrl.todoInput" size="50" placeholder="Add New">
<input type="submit" value="Add New">
</form>
<br>
<div ng-repeat="x in $ctrl.todoList">
<input type="checkbox" ng-model="x.done"> <span ng-bind="x.todoText"></span>
</div>
<p><button ng-click="$ctrl.remove()">Remove marked</button></p>
</div>
And the javascript code-
angular.
module('dashboard').
component('dashboard', {
templateUrl: 'dashboard/dashboard.html',
controller: ['$routeParams','$http',
function dashboardController($routeParams,$http) {
this.todoList = [{todoText:'Clean House', done:false}];
this.todoAdd = function() {
this.todoList.push({todoText:this.todoInput, done:false});
this.todoInput = "";
};
this.remove = function() {
var oldList = this.todoList;
this.todoList = [];
angular.forEach(oldList, function(x) {
if (!x.done) this.todoList.push(x);
});
};
//Rest of the controller code
}
]
});
You need to have empty dependencies passed to your module while declaring,
change it as,
angular.
module('dashboard',[]).
DEMO
var app = angular.module('myFirstApp', []);
app.controller('myCtrl', function () {
this.todoList = [{
"todoText": "run today",
"done": false
},
{
"todoText": "read today",
"done": false
}];
});
<html>
<head>
<title>My First AngularJS App</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<h1>My First AngularJS App</h1>
<div ng-app="myFirstApp" ng-controller="myCtrl as ctrl">
<div ng-repeat="x in ctrl.todoList">
<input type="checkbox" ng-model="x.done"> <span ng-bind="x.todoText"></span>
</div>
</div>
</body>
</html>

Angular JS collect all input values from a div

I am new to Angular JS, I created a div with input elements and I didn't use ng-model for input boxes.
<div class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat=" x in $ctrl.outputProductAttributeValueList">
{{x}} <input type="text" />
</p>
<br>
<button type="submit" ng-click="$ctrl.onRankingFormSubmit()"> SUBMIT</button>
</div>
</div>
When I click on submit button I have to access all input values .Please help me how to do that .. I tried as below.
angular.module("productList")
.component("productList",{
templateUrl : "product-list/product-list.template.html",
controller : ["$http" ,"$scope","$document",function productListController($http,$scope,$document){
var self = this;
self.outputProductAttributeValueList =[ "age", "gender","all"];
self.onRankingFormSubmit = function () {
var queryResult = $document[0].getElementById("rankingForm")
console.log(queryResult);
// HERE queryResult is printing how to proceed further
};
}]
});
Now I want to collect all those input values dynamically created by ng-repeat. Please tell me how to do that ?
AngularJS ngModel is the standard approach for binding the view into the model instead of interacting directly with the DOM.
You can get all the inputs within the div id="rankingForm" you can do:
var inputs = $document[0]
.getElementById('rankingForm')
.getElementsByTagName('input');
Or by using Document.querySelectorAll():
var inputs = $document[0].querySelectorAll('#rankingForm input');
Once you have the inputs than iterate over all of them to get the values.. Notice that I have added attribute name to the inputs:
Code whitout ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
$scope.onRankingFormSubmit = function () {
var inputs = $document[0].querySelectorAll('#rankingForm input');
inputs.forEach(function(input) {
console.log(input.name + ': ' + input.value);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" name="{{x}}" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>
Code with ngModel:
angular
.module('App', [])
.controller('AppController', ['$scope', '$document', function ($scope, $document) {
$scope.outputProductAttributeValueList = ['age', 'gender', 'all'];
// Model inputs
$scope.inputs = {};
$scope.onRankingFormSubmit = function () {
$scope.outputProductAttributeValueList.forEach(function(input) {
// Access to model inputs: $scope.inputs[input]
console.log(input + ': ' + $scope.inputs[input]);
});
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.9/angular.min.js"></script>
<div ng-app="App" ng-controller="AppController" class="row">
<br>
<div class="col-sm-10" id="rankingForm" >
<p ng-repeat="x in outputProductAttributeValueList">
{{x}} <input type="text" ng-model="inputs[x]" />
</p>
<br>
<button type="submit" ng-click="onRankingFormSubmit()">SUBMIT</button>
</div>
</div>

How to propogate a changing scope variable through a function in AngularJs?

For example, if I have the following case:
function ACtrl($scope) {
$scope.title = "Title";
$scope.funkyString= funkyAndComplexStuff($scope.title);
function funkyAndComplexStuff(title) {
/*...*/
return title;
}
}
With html:
<div ng-app>
<div ng-controller="ACtrl">
<div>
{{title}} and length {{funkyString}}
<input type="text" ng-model='title' />
</div>
</div>
</div>
I would like the $scope.funkyString to update every time $scope.title gets changed.
As far as I see I have 2 options:
Using a watch on the variable
Creating a filter I could apply on $scope.funkyString
But both of those sound unndecessarily heavy. Is there anything else I could use to post-process the data as soon as it gets changed?
EDIT:
Modified my example so that people are hopefully less confused.
I would try something like this, so it can handle changes to $scope.title from other fields of code also
<div ng-controller="ACtrl">
<div>
{{title}} and length {{ funkyAndComplexStuff(title) }}
<input type="text" ng-model='title' />
</div>
</div>
You could do title.length as #ssilas777 has suggested. You can also set the $scope variable to be a function. As I understand it, the function will be called during the scope's $digest cycle, which will fire when any bound model changes. See this plunkr: http://plnkr.co/edit/9xspXj5ND8seEX2LNeMe?p=preview
See this HTML:
<input type="text" ng-model="title" />
Num chars: <span ng-bind="numCharsInTitle()"></span>
and the JS:
$scope.title = "The Title";
$scope.numCharsInTitle = function() {
return $scope.title.length;
}
Like ssilas777 and Charlie S and you said you can use $watch, custom $filter or function in $scope
But for me it's complicated to maintain code with function linked to the view. I prefere using $watch because all the processing is in the controller and only $scope.numberOfChars is present in the view.
If you use this many time, I would suggest you to create a custom filter.
angular.module('app',[])
.controller('ACtrl',
function ($scope) {
$scope.title = "Title";
getNumberChars($scope.title);
function getNumberChars(title) {
$scope.numberOfChars = title.length;
};
$scope.getNumberChars = function() {
return $scope.title.length;
};
$scope.$watch('title',getNumberChars);
})
.filter('customFilter', function() {
return function(input) {
return input.length;
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ACtrl">
<div>
{{title}} and length {{numberOfChars}} or {{title.length}} or {{getNumberChars()}} or {{title | customFilter}}
<input type="text" ng-model='title' />
</div>
</div>
</div>
ng-change could be a simple solution depending on the element to which your title model is bound. If it's an input like in the example this might could work:
app.controller('MainCtrl', function($scope) {
$scope.title = "Title";
$scope.funkyAndComplexStuff = function(title) {
/*...*/
$scope.funkyString = title.length;
}
});
...
<body ng-controller="MainCtrl">
{{title}} and length {{funkyString}}
<input type="text" ng-model='title' ng-change="funkyAndComplexStuff(title)" />
</body>
Why not just:
function ACtrl($scope) {
$scope.title = "Title";
$scope.funkyAndComplexStuff = function () {
/*..do stuff with $scope.title..*/
return $scope.title; // or whatever
}
}
With html:
<div ng-app>
<div ng-controller="ACtrl">
<div>
{{title}} and length {{funkyAndComplexStuff()}}
<input type="text" ng-model='title' />
</div>
</div>
</div>
Not sure why somebody downvoted, but here is a demo: http://jsfiddle.net/xhdk3f25/1/

how to create object while using ng-repeat and array in angularjs

Hello Everyone I have face a problem to create a object with ng-repeat. when i declare the Object then the same value in filled in the text box which has same ng-model value. if i am not Declare the object then duplicacy is not occures.
If i am declare the $scope.user = {}; in js file then problem is occures. please check this. Give me a solution ASAP.
My Fiddle Link Please Check This http://jsfiddle.net/Ladjkp5s/1/
Here is my Html file
<div ng-app="myApp">
<div ng-controller='MainController' ng-init="start = 0; end = 5;">
Start: <input ng-model="start"> End: <input ng-model="end">
<ul>
<li ng-repeat="item in items | slice:start:end">{{item + 1}}
<div>
Name: <input type="text" ng-model="user.name"><br>
Address: <input type="text" ng-model="user.add"><br>
Phone: <input type="text" ng-model="user.phn"><br>
ZipCode: <input type="text" ng-model="user.zip">
</div>
</li>
</ul>
</div>
</div>
Here is my JS File
var app = angular.module('myApp', []);
app.filter('slice', function() {
return function(arr, start, end) {
return arr.slice(start, end);
};
});
app.controller('MainController', function($scope) {
$scope.items = [];
$scope.user ={};
for (var i = 0; i < 5; i++) $scope.items.push(i);
});
Thanks.
The problem is that you are using same ng-model for every item.(user.fieldName) you have to use item.fieldName.
<div ng-app="myApp">
<div ng-controller='MainController' ng-init="start = 0; end = 5;">
Start: <input ng-model="start"> End: <input ng-model="end">
<ul>
<li ng-repeat="item in items | slice:start:end">{{item.index + 1}}
<div>
Name: <input type="text" ng-model="item.name"><br>
Address: <input type="text" ng-model="item.add"><br>
Phone: <input type="text" ng-model="item.phn"><br>
ZipCode: <input type="text" ng-model="item.zip">
</div>
</li>
</ul>
</div>
</div>
http://jsfiddle.net/3akwk7tv/
Yuu can not loop in controller function, but u can create controller that loops in html like in this example
<ul>
<li ng-repeat="theItem in myData.items">{{theItem.text}}</li>
</ul>
<script>
angular.module("myapp", [])
.controller("MyController", function($scope) {
$scope.myData = {};
$scope.myData.items = [ {text : "one"}, {text : "two"}, {text : "three"} ];
});
</script>

Categories