list not displaying in angular binding? - angularjs

I am trying my first angular js list example. Having issues displaying the list, there are no errors in the console:(
html
<body ng-controller="mycontroller">
<form ng-submit="addtask()">total nr of tasks: {{myvar.length}}
<br />remaining: {{remaining()}}
<input type="text" ng-model="newtask" />
<ul ng-repeat="var in myvar">
<li>
<input type="checkbox" ng-model="myvardone" /> <span class="done-{{myvardone}}">{{var.text}}</span>
</li>
</ul>
<button type="submit">add</button>
</form>
</body>
script:
function mycontroller($scope) {
$scope.myvar = [{
text: 'bert',
done: false
}, {
text: 'ed',
done: true
}, {
text: 'pet',
done: false
}];
$scope.addtask = function () {
$scope.myvar.push({
text: $scope.newtask,
done: false
});
}
$scope.remaining = function () {
var count = 0;
angular.forEach($scope.myvar, function (t) {
if (t.done) {
count++
} else {
count += 0;
}
});
return count;
}
}
jsfiddle:http://jsfiddle.net/dingen2010/vc2bC/3/

simple demo can be like
<html ng-app>xxxxx</html>
don't forget "ng-app"

Several things
One. missed ng-app
Two. You should not repeating ul, but li
<li ng-repeat="var in myvar">
<input type="checkbox" ng-model="var.done" />
<span class="done-{{var.done}}">{{var.text}}</span>
</li>
Three. when you add, you need to have task name entered.
Four, you don't need remaining function. use filter
{{ (myvar | filter:{done:true}).length }}
http://jsfiddle.net/vc2bC/10/

Darn, Awakening beat me to it... :/ But yeah, just simply move the ng-controller tag to a containing and put a ng-app tag on the html tag. Here:
enter code herehttp://jsfiddle.net/vc2bC/8/

Related

AngularJS. Dynamically added inputs don't affect $valid

trying to make a dynamically composed form.
Fields and attributes come from server. Angular should get them and generate a form.
I decided to use directive and runtime compilation.
Mostly all works except a few things.
The problem: $valid is undefined for compiled fields.
For static fields is works.
Please give me an advice.
app = angular.module('dyno', []);
app.controller("fieldCompilation", function($scope) {
$scope.list = [{
id: "0",
name: "A"
},
{
id: "1",
name: "B"
},
{
id: "2",
name: "C"
},
];
});
app.directive("otcDynamic", function($compile) {
return {
link: function(scope, element) {
// Add Text Input with pattern validation and required attr
var template = "<input type='text' name='input3' ng-model='input3' placeholder='input3 [0-9]{2} required' pattern='[0-9]{2}' required='true'/>";
var linkFn = $compile(template);
var content = linkFn(scope);
angular.element(document.getElementById("f3")).append(content);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.2/angular.min.js"></script>
<div ng-app="dyno">
<div ng-controller="fieldCompilation">
<br><b> Static Input:</b>
<ng-form name="form1">
<div id="f1">
1. Input <input type='text' name='input1' ng-model='input1' placeholder='input1 [0-9]{2} required' pattern='[0-9]{2}' required='true' /><br>
</div>
<br><b> Dynamic Inputs:</b>
<div otc-dynamic>
<div id="f3">
3. Input
</div>
</div>
<br> <b>Details</b>
<div>
Counter: {{ message }}
</div>
<div>
Model Input1: {{ input1 }}
</div>
<div>
Model input3: {{ input3 }}
</div>
<div>
Validation input1: {{ form1.input1.$valid }}<br> Validation input3: {{ form1.input3.$valid }}<br> Validation form1: {{ form1.$valid }}<br>
</div>
</ng-form>
</div>
</div>
Fiddle

Angular - inside an ng-repeat, checkbox state to affect only one element

If I have for example a simple todo list:
HTML
<ul ng-repeat="todos in keyVar.list">
<li ng-class="{ 'completed' : keyVar.toggle }">
{{ todos }}
<input ng-if="!keyVar.toggle" type = "checkbox" ng-click="keyVar.toggle=true" >
<input ng-if="keyVar.toggle" type = "checkbox" checked= "true" ng-click="keyVar.toggle=false" ></input>
</li>
</ul>
JS
angular.module("todoApp", [])
.controller("mainCtrl", function(){
var keyVar = this;
keyVar.title ="Angular Todos";
keyVar.list=[];
keyVar.toggle = false;
keyVar.todosArr = function(){
keyVar.list.push(keyVar.todo)
keyVar.todo = "";
}
});
When I run this, I can add a todo, and check and uncheck the checkbox which toggles a class of completed, but it gives the class to every todo and if I check one checkbox, all of them go checked. I think I have to use something like keyVar.list[$index]? But I'm not sure where to use it or how.
Try like this. I define for each todo a status. and bind that to checkbox. when user click on checkbox change it.
angular.module("todoApp", [])
.controller("mainCtrl", function(){
var keyVar = this;
keyVar.title ="Angular Todos";
keyVar.list=[
{
"title":"Todo1",
"status":false
},
{
"title":"Todo2",
"status":false
}
];
keyVar.todosArr = function(){
keyVar.list.push({title:keyVar.todo,status:false})
keyVar.todo = "";
}
});
.completed{
text-decoration: line-through;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="todoApp" ng-controller="mainCtrl as keyVar" class="container">
<input type="text" ng-model="keyVar.todo">
<button ng-click="keyVar.todosArr()">Add Todo</button>
<ul ng-repeat="todos in keyVar.list">
<li ng-class="{ 'completed' : todos.status }">
{{ todos.title }}
<input ng-model="todos.status" type = "checkbox" ng-click="keyVar.toggle=true" >
</li>
</ul>
</div>
Try use ng-checked instead of ng-click.
<input ng-if="!keyVar.toggle" ng-checked="keyVar.toggle=true">

Apply logic to every element in an ng-repeat upon ng-click (AngularJS)

I'm trying to build a media library in which only one image can be selected at a time. To do this, I have a list generated with AngularJS's ng-repeat function. So far, when I click on an element, it adds a highlighting class to a child div and toggles the visibility of a child form element. How can I make the click do the opposite for every other element in the ng-repeat?
<li ng-click="show=!show" ng-repeat="media in media">
<div ng-if="show" class="selected">
<input class="bulk-check" type="hidden" name="ids[]" value="#include('_helpers.media_id')">
</div>
</li>
You could just save displayed media in a temp variable in your controller and have 2 functions 1) set the media object on click of item 2) can show function which checks for object equality.
Controller:
var shownMedia = $scope.medias[0]; //Set you default media
$scope.selectMedia = function(media) {
shownMedia = media; //on click, set the new media as selected media
}
$scope.canShow = function(media) {
return angular.equals(shownMedia, media); //Check if this is the displayed media
}
View:
<li ng-click="selectMedia(media)" ng-repeat="media in medias">
{{media.name}}
<div ng-if="canShow(media)" ng-class="{selected : canShow(media)}">
{{media.description}}
<input class="bulk-check" type="hidden" name="ids[]" value="#include('_helpers.media_id')">
</div>
</li>
Example implementation Demo
angular.module('app', []).controller('ctrl', function($scope) {
$scope.medias = [{
name: 'media1',
description: "media1"
}, {
name: 'media2',
description: "media2"
}, {
name: 'media3',
description: "media3"
}];
var shownMedia = $scope.medias[0];
$scope.selectMedia = function(media) {
shownMedia = media;
}
$scope.canShow = function(media) {
return angular.equals(shownMedia, media);
}
});
.selected{
color:blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<ul>
<li ng-click="selectMedia(media)" ng-repeat="media in medias">
<span ng-class="{selected : canShow(media)}">{{media.name}}</span>
<div ng-if="canShow(media)">
{{media.description}}
<input class="bulk-check" type="hidden" name="ids[]" value="#include('_helpers.media_id')">
</div>
</li>
</ul>
</div>
This should work
<li ng-repeat="media in mediaList" ng-click="media.show=!media.show" >
<div ng-if="media.show" class="selected">
<input class="bulk-check" type="hidden" name="ids[]" value="#include('_helpers.media_id')">
</div>
</li>

parseInt not converting multiple string to int

it was a very simple but don't no why i can't solve it.
I am trying to convert string to integer from json, it converts 1st object but from second object it doesn't:
HTML:
<body ng-controller="myApp">
<ul ng-repeat="vals in json_arr" ng-init="parseId(vals)">
<li>
<input type="number" ng-model="vals.id" />
</li>
<li>
<input type="number" ng-model="vals.id1" />
</li>
<li>
<input type="number" ng-model="vals.id2" />
</li>
</ul>
</body>
Controller:
app.controller('myApp', function($scope) {
$scope.json_arr = [{
'id': '1',
'id1': '2',
'id2': '3'
}];
$scope.parseId = function(val) {
val.id = parseInt(val.id);
}
});
DEMO PLUNKER
Aahhhhh that's my mistake, In parseId function i only parse val.id.
The correct 1 is:
$scope.parseId = function(val) {
val.id = parseInt(val.id);
val.id1 = parseInt(val.id1);
val.id2 = parseInt(val.id2);
}
change your code with this one
$scope.parseId = function(val) {
val.id = parseInt(val.id);
val.id1 = parseInt(val.id1);
val.id2 = parseInt(val.id2);
}
or you can change your json_arr variable than you don't need to change string to int
$scope.json_arr = [{
'id': 1,
'id1': 2,
'id2': 3
}];
Directives are executed in order from highest priority to lowest priority when defined on the same element. ng-repeat has a directive priority level of 1000, but ng-init has a directive priority of 450. ng-repeat also has a terminal property - meaning it is the last directive to execute, and no other directives can execute after it. There-in lies the problem. The ng-repeat executes first, and because it is terminal, it will not allow ng-init to execute after.
To solve this, move the ng-init to the first li below:
<body ng-controller="myApp">
<ul ng-repeat="vals in json_arr">
<li ng-init="parseId(vals)">
<input type="number" ng-model="vals.id" />
</li>
<li>
<input type="number" ng-model="vals.id1" />
</li>
<li>
<input type="number" ng-model="vals.id2" />
</li>
</ul>
</body>
This works because ng-model has a priority of 0, so it will execute after ng-init.
[EDIT]
I realized there is a logic error in the code you posted. The other two answers have already addressed it, but I'll post it again here for completeness:
$scope.parseId = function(val) {
val.id = parseInt(val.id);
val.id1 = parseInt(val.id1);
val.id2 = parseInt(val.id2);
}

Advice on the correct use of ngModel

I' new to AngularJS and have a following ambiguity with usage of ngModel. I want to give to the user possibility to generate unlimited number of "name": "value" pairs. So I generating div with ng-repeat for every element from pair. Here is my html:
<div ng-app>
<div ng-controller="TestCtrl">
<input type="button" value="+" ng-click="addNewRow();"/>
<div ng-repeat="a in range(itemsNumber)"><input type="text" name="key"/> : <input type="text" name="value"/></div>
</div>
</div>
And the JavaScript:
function TestCtrl($scope) {
$scope.itemsNumber = 1;
$scope.range = function() {
return new Array($scope.itemsNumber);
};
$scope.addNewRow = function () {
$scope.itemsNumber++;
}
};
Here is working js fiddle:
http://jsfiddle.net/zono/RCW2k/
I want to have model for this generating items but not sure how to do it.
I would appreciate any ideas and tips.
Best regards.
Edit:
I have create other solution. It can be viewed in this fiddle
http://jsfiddle.net/zono/RCW2k/8/
But is this solution is good idea?
Here is a fiddle: http://jsfiddle.net/RCW2k/13/
You should just create an array on the scope and it's also your model:
controller:
function TestCtrl($scope) {
$scope.items = [{key:"hello",value:"world"}]
$scope.addNewRow = function () {
$scope.items.push({key:"",value:""});
}
};
html:
<div ng-controller="TestCtrl">
<input type="button" value="+" ng-click="addNewRow();"/>
<div ng-repeat="item in items">
<input type="text" name="key" ng-model="item.key"/> :
<input type="text" name="value" ng-model="item.value"/>
</div>
</div>

Resources