Trying to create a function that will remove the selected checkbox items from the array but can't seem to figure it out. I have tried using splice and .pop() but it just won't remove the items I select. I think the best way would be to use an if statement but I do not know how to write it so that it shows true or false. Please help!!!
JS:
.controller('toDoCtrl', function($scope, toDoFactory){
//set $scope variables
$scope.tasks = toDoFactory.tasks;
$scope.removeTasks = toDoFactory.removeTasks;
})
.factory('toDoFactory', ['$http', function($http){
var toDo = {
tasks: [],
removeTasks: function(selectedTask){
angular.forEach(toDo.tasks, function(value, selectedTask){
var i = toDo.tasks.indexOf(value);
toDo.tasks.splice(toDo.tasks.indexOf(i), 1);
});
}
};
return toDo;
}])
HTML:
<button ng-click="removeTasks()">Remove</button>
I did not really understood if you wanted to delete all selected tasks or just one.
Anyway, you can do this for example :
JS:
app
.controller('toDoCtrl', function($scope, toDoFactory){
//set $scope variables
$scope.data = {};
$scope.data = toDoFactory.data;
$scope.removeTasks = toDoFactory.removeTasks;
$scope.removeTask = toDoFactory.removeTask;
})
.factory('toDoFactory', ['$http', function($http){
var toDo = {
data : {
tasks: [
{text: "hello world", done: false},
{text: "hello world2", done: false},
{text: "hello world3", done: false}
]
},
removeTasks: function(){
toDo.data.tasks = toDo.data.tasks.filter(function(task){
return !task.done;
});
},
removeTask: function(index){
toDo.data.tasks.splice(index, 1);
},
};
return toDo;
}]);
HTML:
<body ng-controller="toDoCtrl">
<div ng-repeat='task in data.tasks'>
<input type='checkbox' ng-model='task.done' />
<span>{{task.text}}</span>
</div>
<br/>
<button ng-click="removeTasks()">Remove</button>
</body>
Plunkr :
https://plnkr.co/edit/bTG0fEUZl1uoTIFT1NhC?p=preview
Related
Here is my code below. The ng-change of individual checkboxes is not getting triggered when it is changed by clicking Select All button but it is getting triggered when it's selected individually. I need the itemChecked method to be triggered when the Select All button is clicked.
Here is a Codepen Link for the same
HTML
<div ng-app="Test">
<div ng-controller="TestController">
<form>
<div ng-repeat="item in list track by $index">
<input type="checkbox" ng-model="item" ng-change="itemChecked($index)">{{$index + 1}}
</div>
</form>
<button ng-click="toggleSelection()">Select all</button>
</div>
</div>
JavaScript
var app = angular.module("Test", []);
app.controller("TestController", [
"$scope",
"$http",
function($scope, $http) {
$scope.list = [false, false, false, false, false];
$scope.itemChecked = function(i) {
console.log(i);
};
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
}
};
}
]);
Please let me know what I need to change or what I am doing wrong to fix this.
You have set wrong variable in ng-model. The ng-model section should be:
ng-model="list[$index]"
To listen the collection, you have to use the following:
$scope.$watchCollection
It is working perfectly in the following code, check the code snippet:
var app = angular.module("Test", []);
app.controller("TestController", [
"$scope",
"$http",
function($scope, $http) {
$scope.list = [false, false, false, false, false];
$scope.itemChecked = function(i) {
console.log(i);
console.log($scope.list[i]);
};
$scope.$watchCollection('list', function (oldValue, newValue) {
//console.log(oldValue);
//console.log(newValue);
//console.log($scope.list);
for(var i = 0; i < oldValue.length;i++){
if (oldValue[i]!==newValue[i]) {
$scope.itemChecked(i);
}
}
});
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="Test">
<div ng-controller="TestController">
<form>
<div ng-repeat="item in list track by $index">
<input type="checkbox" ng-model="list[$index]" ng-change="itemChecked($index)">{{$index + 1}}
</div>
</form>
<button ng-click="toggleSelection()">Select all</button>
</div>
</div>
What you need is watchCollection method. ngChange works only if the value is changed from HTML. It is not triggered when the value is changed from controller.
app.controller("TestController", [
"$scope",
"$http",
function($scope, $http) {
$scope.list = [false, false, false, false, false];
$scope.itemChecked = function(i) {
console.log(i);
};
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
}
};
/*********************************************************/
$scope.$watchCollection('list', function (newVal, oldVal) {
console.log('collection changed') });
}
/*********************************************************/
]);
Or If you just want itemChecked method to be called whenever the selectAll button is clicked, Then just call itemChecked inside toggleSelection method.
$scope.toggleSelection = function() {
for (var i in $scope.list) {
$scope.list[i] = true;
$scope.itemChecked(i);
}
};
I'm trying to pre-fill a form with a data from a controller.
Simple code looks like
<div ng-app="app" ng-controller="MainCtrl">
<input name="widget.title" ng-model="widget.title">
<input name="widget.content" ng-model="widget.content">
<button ng-click="set('foo')">set to foo</button>
</div>
and
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.widget = {title: 'abc'};
$scope.widget = {content: 'test'};
$scope.set = function(new_title) {
this.widget.title = new_title;
}
});
but it always pre-fill only last input field
JSFiddle: http://jsfiddle.net/b40nLuf2/
In your case, you overrides the first $scope.widget ($scope.widget = {title:'abc'}) with the second ($scope.widget = {content:'test'}).
You have to define one object $scope.widget with two attributes, title and content, in this way:
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.widget = {
title: 'abc',
content: 'test'
};
$scope.set = function(new_title) {
this.widget.title = new_title;
}
});
you can try this code snippets
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.widget = {title: 'abc',content: 'test'};
$scope.set = function(new_title) {
this.widget.title = new_title;
}
});
JSFIDDLE : click here to see
you need to create your object like this
$scope.widget = {
title: 'abc',
content: 'test'
};
I have fetched docs from my database. now what I want to do is based on different doc.statuses, want to display different messages. How to go about it?
<p>
<a target="_blank" style="margin-right:5px" ng-repeat="doc in homeCtrl.getDocs(docType.objectId)" href="{{doc.document.url}}">
<div ng-if="doc.status == 'approved'">Hello</div>
<span class="label label-success"><i class="glyphicon glyphicon-hourglass"></i>{{doc.status}}</span>
<br>{{doc.comment}}<br>
</a>
</p>
so the ng-if in the div is not working. How to refer to the doc used in ng-repeat?
EDIT:
I still can't figure out. My controller looks like this(I'm using a Parse backend)
The controller looks like this
class HomeController {
constructor($scope, $state, itemsService, $location, $ionicLoading) {
'ngInject';
const self = this;
self.UserDocument = Parse.Object.extend('UserDocument');
self.$scope = $scope;
self.$scope.user = {};
self.$scope.objUserDocument = {};
self.$scope.userDocumentTypes = [];
self.loading = $ionicLoading;
// self.$scope.docs = [];
$scope.$on("$ionicView.beforeEnter", function(event, data) {
if (!Parse.User.current()) {
$location.url('/signup');
} else {
// self.$scope.user = window.buddy;
self._getDocumentTypes();
// self.$scope.user.firstName = objUser.get('firstName');
// self.$scope.user.lastName = objUser.get('lastName');
// console.log(objUser.get('docs'));
}
});
window.homeCtrl = this;
}
getDocs(id) {
const self = this;
if (self.$scope.user.docs && self.$scope.user.docs.length) {
var docs = self.$scope.user.docs.filter(d => id == d.docType.objectId);
return docs;
} else {
return [];
}
}
}
export default HomeController;
````
ng-if works fine:
HTML:
<div ng-repeat="item in items">
<span>{{item.id}}</span>
<span ng-if="item.status === 'approved'">approved</span>
<span ng-if="item.status === 'rejected'">rejected</span>
</div>
JS:
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
$scope.items = [
{status: 'approved', id: 1},
{status: 'approved', id: 2},
{status: 'rejected', id: 3},
{status: 'rejected', id: 4}
]
}])
Here is the plnkr: http://plnkr.co/edit/wIX46rZHBNGHdv1S3LKg?p=preview
Try to move the function that retrieves the docs inside you controller and pass the result to ng-repeat instead.
ng-repeat="doc in docs"
and
.controller('YourController', function($scope) {
$scope.docs = getDocs(id);
});
I already have seem other topics with this kind of issue, but no one could help me... So here is my issue:
I have a navbar with a button for search, this buttons makes and get request from a webservice and returns a json object which must be apply to fill an table list. The problem is, my button and my table are in separated controllers, and it does work like I expected.
var app = angular.module('clientRest', []).controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.getContatos();
}]).controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
}]).service('loadLista', function() {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
}
};
});
My code...
When I call listar() from pesquisa controller I need to send received data to $scope.contatos from lista controller to make my ng-repeat work, everything with a single click.
How can I do it?
Thanks everyone
Better to use a service to share data between two controllers / modules as this might be the best approach. You can refer the code segment given below to understand the concept.
angular.module('app.A', [])
.service('ServiceA', function() {
this.getValue = function() {
return this.myValue;
};
this.setValue = function(newValue) {
this.myValue = newValue;
}
});
angular.module('app.B', ['app.A'])
.service('ServiceB', function(ServiceA) {
this.getValue = function() {
return ServiceA.getValue();
};
this.setValue = function() {
ServiceA.setValue('New value');
}
});
In order to trigger the data receipt event, you may use
Broadcast / emit messages - with #broadcast / #emit
An angular promise with a call back
Controller initiation function to reload the previously read information from a service
.controller('MyController', function($scope, ServiceA) {
$scope.init = function() {
$scope.myValue = ServiceA.getValue();
};
// Call the function to initialize during Controller instantiation
$scope.init();
});
Use $rootScope.$emit to emit a change event when setting the variable and use $on to get the value in the lista controller. I used customListAr here just to demostrate a button click. Does this help?
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', '$rootScope',
function($scope, loadLista, $rootScope) {
console.log(loadLista);
$scope.contatos = loadLista.getContatos();
$rootScope.$on('change', function() {
$scope.contatos = loadLista.getContatos();
});
}
])
.controller('pesquisa', ['$scope', '$http', 'loadLista',
function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
$scope.customListAr = function() {
loadLista.setContatos(["item 1" , "item 2", "item 3"]);
}
}
])
.service('loadLista', ['$rootScope',
function($rootScope) {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
$rootScope.$emit('change');
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="clientRest">
<div ng-controller="lista">
<ul>
<li ng-repeat="a in contatos">{{a}}</li>
</ul>
</div>
<div ng-controller="pesquisa">
<button ng-click="customListAr()">Click Me</button>
</div>
</div>
Your problem is that when you do $scope.contatos = loadLista.getContatos(); you are setting a static value, and angular is unable to effectively create a watcher for that object because your setContatos method is creating a new object each time. To get around this, have the controller's scope hold a reference to the parent object and then it will automatically have a watcher on that object.
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.contatos;
}])
.controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato"
).success(function (response) {
loadLista.contatos.data = response;
});
};
}])
.service('loadLista', function() {
var lista = {
contatos: {},
};
return lista;
});
// view:
<ul>
<li ng-repeat="contato in contatos.data">
{{ contato }}
</li>
</ul>
EDIT - lots of changes
After my page loads, I have some javascript function calls that return data which will be used in my markup to populate tag options.
Currently the issue is this: When the values are changed by the javascript outside ( and even inside the AngularJS controller). The view is not being updated. I have tried wrapping scope assignments in $scope.$apply(...) however this just results in a $digest() already in progress error.
AngularJS Code:
app.service('userService', ['$http', function($http) {
var userModel = {
qGroupZero: '',
qGroupOne: '',
qGroupTwo: ''
};
var states = '';
return{
getUserModel: function() {
return userModel;
},
getStates: function() {
return states;
},
loadChallengeQuestions: function() {
var userEnrollmentChallenge = getChallengeQuestions();
console.log('loadChallengeQuestions()');
userModel.qGroupZero = userEnrollmentChallenge.challengeQuestions.questionGroup[0];
userModel.qGroupOne = userEnrollmentChallenge.challengeQuestions.questionGroup[1];
userModel.qGroupTwo = userEnrollmentChallenge.challengeQuestions.questionGroup[2];
},
loadStates: function(callback) {
console.log('loadStates()');
return $http.get('content/states.json').then(function(result) {
states = result.data;
});
}
};
}]);
app.controller('EnrollmentController', ['$scope', 'userService', '$http', function($scope, userService, $http) { //Dependencies and Constructor function.
$scope.userService = userService;
$scope.states = [];
userService.loadChallengeQuestions();
var userModel = userService.getUserModel();
$scope.qGroupZero = userModel.qGroupZero.challengeQuestion; //<-- This assignment is not updated in the view.
userService.loadStates().then(function(result) {
$scope.states = userService.getStates(); //<-- This assignment is not updated in the view.
});
}]);
The content of challengeQuestion is a JSON array of 7 items.
The Markup:
<select ng-model="selectionOne"
name="question1"
ng-options="opt as opt.questionText for opt in qGroupZero">
</select>
<select ng-model="state"
name="state"
ng-options="opt as opt.abbreviation for opt in states"
class="required">
</select>
So at this point. I have all my resources. And I just need to find a way to get AngularJS to re-evaluate the ng-options value (a $scope.value) and redraw the content? I think I'm saying that right...
Why do I feel that this should be easy? And yet three days later here I am :D
Thanks for reading and helping!!!
What if you use the angular $http service and promise objects instead?
app.service('userService', ['$http', function($http) {
var userModel: {
qGroupZero: '',
qGroupOne: '',
qGroupTwo: ''
};
var states = '';
return{
getUserModel: function(){
return userModel;
},
getStates: function(){
return states;
},
loadChallengeQuestions: function(userEnrollmentChallenge) {
console.log('loadChallengeQuestions()');
userModel.qGroupZero = userEnrollmentChallenge.challengeQuestions.questionGroup[0];
userModel.qGroupOne = userEnrollmentChallenge.challengeQuestions.questionGroup[1];
userModel.qGroupTwo = userEnrollmentChallenge.challengeQuestions.questionGroup[2];
},
loadStates: function(){
return $http.get('content/states.json').then(function(result){
states = result.data;
});
}
}
});
app.controller('EnrollmentController', ['$scope', 'userService', function($scope, userService) { //Dependencies and Constructor function.
$scope.states = [];
userService.loadStates().then(function(result){
var userModel = userService.getUserModel();
$scope.states = userService.getStates();
$scope.qGroupZero = userModel.qGroupZero.challengeQuestion;
});
}]);