Change event is not called when checked value changed using ref - checkbox

I was trying to create a select all feature. Following is my component,
(function(){
var template = ' <table>\
<tr>\
<td rowspan=2><input type="checkbox" #change="allSelectChanged"/>All</td>\
</tr>\
<tr v-for="i in rows">\
<td ><input type="checkbox" ref="select" #change="changedSelection(i,$event)" />Selection {{i}}</td>\
</tr>\
</table>';
var component = {
template : template,
data:function(){
return {
rows:5
}
},
methods:{
allSelectChanged:function(e){
_.each(this.$refs.select,function(s){
s.checked = e.target.checked;
});
},
changedSelection:function(i,e){
console.log("Selection changed",i,e.target.checked);
}
}
}
Vue.component('sample', component);
})();
var app = new Vue({
el: '#app',
data: {
},
methods:{
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://underscorejs.org/underscore-min.js"></script>
</style>
<div id="app">
<sample />
</div>
When I checked/unchecked any checbox changedSelection function is called. But when I checked/unchecked all checkbox, check boxes are getting selected but respective changedSelection function is not getting called.
Why changedSelection is not called when the change is made through ref??

Instead set new element in vue data and use bind with v-model="selection"
new Vue({
el:'#app',
data:{
rows:[{id:1,sel:false},{id:2,sel:false},{id:3,sel:false},{id:4,sel:false},{id:5,sel:false}],
selection:false,
selAll:false
},
methods:{
changedSelection:function(i){
console.log(i.id +" is "+ (i.sel?' checked ': 'unchecked') );
},
changedAllSelection:function(){
for(let i in this.rows){
this.rows[i].sel = this.selAll;
console.log(this.rows[i].id +" is "+ (this.rows[i].sel?' checked ': 'unchecked') );
}
console.log("Select All : " + this.selAll);
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div>
<input type="checkbox" ref="select" v-model="selAll" #change="changedAllSelection" />Selection All : {{(selAll?' checked ': 'unchecked')}}
<div v-for="i in rows">
<input type="checkbox" ref="select" v-model="i.sel" #change="changedSelection(i)" />Selection {{i.id}} : {{(i.sel?' checked ': 'unchecked')}}
</div>
</div>
</div>

Related

angularjs - Update ng-model value from controller?

View 1:
<div ng-controller="ctrl1">
<button ng-click="goToExtendedForm({'name':'aaa'})">
</button>
</div>
ctrl1:
$scope.selectedList = {
name: ""
};
$scope.goToForm = function(e) {
$scope.selectedList.name = e.name;
$state.go('view2');
console.log(e); // prints updated value
};
View 2:
<div ng-controller="ctrl1">
<input
id="name"
name="name"
type="text"
ng-model="selectedList.name"
ng-readonly="true"
/>
</div>
But the input box is always empty, even though to get to the view the goToForm() is called. Why doesn't it update the HTML value?
Views are changed with ui.router's $state.
From your description, your code is supposed to work. Check if you are passing the right parameter into the function. Here is a working demo:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.selectedList = {
name: ""
};
$scope.goToForm = function(e) {
$scope.selectedList.name = e.name;
console.log(e); // prints updated value
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<button ng-click="goToForm({'name':'aaa'})">Change</button>
<br>
<input type="text" ng-model="selectedList.name" ng-readonly="true" />
</div>
Try adding $scope.$apply() at the end of your $scope.goToForm function
Try this ;
HTML Code
<div ng-app>
<div ng-controller="ClickToEditCtrl">
<input
id="name"
name="name"
type="text"
ng-model="selectedList.name"
ng-readonly="true"
/>
<button ng-click="goToForm(testUserDetails)" >Go To</button>
</button>
</div>
</div>
Define controller like this;
function ClickToEditCtrl($scope) {
$scope.selectedList = {
name: ""
};
$scope.testUserDetails ={
name: "nimal"
}
$scope.goToForm = function(e) {
$scope.selectedList.name = e.name;
console.log(e); // prints updated value
};
}

add green background to the label that contains the selected radio input

I am new at angular. I would like that by clicking on the selected radio input, the label turns green. How can I do it?
<div ng-app="myApp">
<div ng-controller="myController">
<div>Which one?</div>
<label class="radio" ng-repeat="eval in evaluators">
<input type="radio" ng-model="cell.evaluator" name="evaluatorOptions" value="{{eval.name}}">{{eval.name}}
</label>
<hr />
<div>You picked: {{cell.evaluator}}</div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
$scope.cell = {
evaluator: "Guava2"
};
$scope.evaluators = [{
name: "Guava1"
}, {
name: "Guava2"
}];
});
http://jsfiddle.net/77axwybr/
You can use ng-class to dynamically set the class of the label using a method on scope that checks the current value with that set in ng-model.
<style>
.selected {
background: green;
}
</style>
<div ng-app="myApp">
<div ng-controller="myController">
<div>Which one?</div>
<label ng-class="{selected: isSelected(eval.name) }" class="radio" ng-repeat="eval in evaluators">
<input type="radio" ng-model="cell.evaluator" name="evaluatorOptions" value="{{eval.name}}">{{eval.name}}
</label>
<hr />
<div>You picked: {{cell.evaluator}}</div>
</div>
</div>
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
$scope.isSelected = (name) => $scope.cell.evaluator === name;
$scope.cell = {
evaluator: "Guava2"
};
$scope.evaluators = [{
name: "Guava1"
}, {
name: "Guava2"
}];
});
http://jsfiddle.net/vsdvcepn/

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">

angularjs not updating model value

In my example I want to update model when user focus the textfield. In short append 'px' string to the existing value.
HTML:
<div ng-app>
<div ng-controller="PixelCtrl">
<div>
{{pixel}}
</div>
<input type="text" ng-focus="updatePX($event)" ng-model="pixel" />
</div>
</div>
JS:
function PixelCtrl($scope) {
$scope.pixel = "120";
$scope.updatePX = function(e){
debugger;
alert(e.target.value);
e.target.value = e.target.value + "px";
$scope.$apply();
}
}
As you all can see I have also used $scope.$apply. Most likely I am doing something wrong.
JSFIDDLE: https://jsfiddle.net/ashwyn/U3pVM/27621/
You don't need to manually add the 'px' text. Simply add it by default
function PixelCtrl($scope) {
$scope.pixel = "120";
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app>
<div ng-controller="PixelCtrl">
<div ng-show="pixel">
{{pixel}} px
</div>
<input type="text" ng-model="pixel" />
</div>
</div>
You must include 1.2.1 angular version. Here is your solution: jsfiddle
<div ng-app>
<div ng-controller="PixelCtrl">
<div>
{{pixel}}
</div>
<input type="text" ng-focus="updatePX($event)" ng-model="pixel" />
</div>
</div>
function PixelCtrl($scope) {
$scope.pixel = "120";
$scope.updatePX = function(e){
e.target.value = e.target.value + "px";
$scope.pixel=e.target.value;
}
}
As #Alexandru Mihai said, upgrade angular version.
See example on jsfiddle.
angular.module("testApp", [])
.controller("PixelCtrl", function($scope) {
$scope.pixel = "120";
$scope.updatePX = function(e) {
if ($scope.pixel && $scope.pixel.indexOf("px") === -1)
$scope.pixel += "px";
}
})
.directive("myPixel", function() {
return {
require: "ngModel",
link: function(scope, element, attr, ngModel) {
element.on("focus", function() {
var val = ngModel.$viewValue;
if (val && val.indexOf("px") === -1) {
ngModel.$setViewValue(ngModel.$viewValue + "px");
element.val(ngModel.$viewValue);
}
})
}
}
})
.directive("myPixelBetter", function() {
return {
scope: {
value: "=myPixelBetter"
},
link: function(scope, element) {
element.on("focus", function() {
if (scope.value && scope.value.indexOf("px") === -1) {
scope.value += "px";
scope.$apply();
}
})
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="testApp">
<div ng-controller="PixelCtrl">
<div>
{{pixel}}
</div>
<div>
With ng-focus
<input type="text" ng-focus="updatePX()" ng-model="pixel" />
</div>
<div>
With custom directive
<input type="text" my-pixel ng-model="pixel" />
</div>
<div>
With custom directive. Better solution
<input type="text" my-pixel-better="pixel" ng-model="pixel" />
</div>
</div>
</div>

Angularjs array push UI does not get's refreshed

I want to show a list of movies and add a new movie by adding it to the array.
The html file:
<!-- FOREACH the movies -->
<div ng-controller="homeController" ng-repeat="movie in movies | orderBy : order">
<div class="movie-wrapper">
<h1>{{movie.name}}</h1>
<p>IMDB: IMDB</p>
</div>
</div>
<!-- ADD a new movie to the array -->
<div ng-controller="homeController">
<h3>Add new movie:</h3>
<form name="movieForm" ng-submit="addMovie(movieInfo)">
<div class="form-group new-movie">
<label for="Title">Title:</label>
<input type="text" class="form-control" name="title" ng-model="movieInfo.title">
</div>
<div class="form-group new-movie">
<label for="IMDB">IMDB:</label>
<input type="text" class="form-control" name="imdb" ng-model="movieInfo.imdb">
</div>
<button type="submit" class="btn btn-primary">Add movie</button>
</form>
</div>
The javascript file:
var app = angular.module('movie-app', ["ngRoute"]);
app.controller("homeController", function($scope) {
$scope.movies = getMovies();
// Method to add a new movie
$scope.addMovie = function(movieInfo) {
$scope.movies.push({
name : movieInfo.title,
imdb_url: movieInfo.imdb
});
console.log("Movie added");
}
});
function getMovies() {
return [{
name: 'Inception',
imdb_url: 'http://www.imdb.com/title/tt1375666/'
}];
}
After pressing the submit button, in the console I did not get any error message, but somehow the UI does not get's refreshed.
I think that somehow the controller does not get a reference/bind to the same array or dom element when I'm pushing the new entry.
First of all, i'm pretty sure you should have an error in your console
You make 3 mistakes :
1. You have an error in your getMovies() function (missing curly brackets {})
function getMovies() {
return [{
name: 'Inception',
imdb_url: 'http://www.imdb.com/title/tt1375666/'
}];
}
Why curly brackets are important ?
name and imdb_url are properties object. In JavaScript, an object must have curly brackets before and after. But your function getMovies returns and array of 1 element, so you have to surround your object with brackets []
2. You also have an error when you call console.log (missing quote ")
console.log("Movie added);
3. And the last one : you have to remove the parenthesis }) (the line after console.log)
The result :
angular.module('movieApp', [])
.controller("homeController", function($scope) {
$scope.movies = getMovies();
// Method to add a new movie
$scope.addMovie = function(movieInfo) {
$scope.movies.push({
name: movieInfo.title,
imdb_url: movieInfo.imdb
});
console.log("Movie added");
};
});
function getMovies() {
return [{
name: 'Inception',
imdb_url: 'http://www.imdb.com/title/tt1375666/'
}];
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="movieApp" ng-controller="homeController">
<!-- FOREACH the movies -->
<div ng-repeat="movie in movies | orderBy : order">
<div class="movie-wrapper">
<h1>{{movie.name}}</h1>
<p>IMDB: IMDB
</p>
</div>
</div>
<!-- ADD a new movie to the array -->
<div>
<h3>Add new movie:</h3>
<form name="movieForm" ng-submit="addMovie(movieInfo)">
<div class="form-group new-movie">
<label for="Title">Title:</label>
<input type="text" class="form-control" name="title" ng-model="movieInfo.title">
</div>
<div class="form-group new-movie">
<label for="IMDB">IMDB:</label>
<input type="text" class="form-control" name="imdb" ng-model="movieInfo.imdb">
</div>
<button type="submit" class="btn btn-primary">Add movie</button>
</form>
</div>
</div>

Resources