I'm using angularJS to build a SPA. I am trying to delete an object from an array in my controller. I am using ng-repeat and can't seem to get my head around this. Here is the related html:
<div class="cat-button" ng-repeat="category in cats" category="category">
<button class=" close-button" ng-click="removeCat()">
<span class="glyphicon glyphicon-remove-sign" aria-hidden=true> </span> </button>{{category.name}}
</div>
This created a div with a button for every object that gets saved to my $scope.cats array. It works fine but I cant figure out how do I use the button in each div to delete that specific object.
When I click on the button , the function on my controller gets called, but this is where I get lost, how do I delete the specific object created dynamically by the user.
This is the related code on my controller:
//Function to delete category
$scope.removeCat = function () {
//I know I have to use splice on my array but how do I Identify the object that needs to be deleted from my array?
};
You can either pass on $index like so:
<button class=" close-button" ng-click="removeCat($index)">
and in your function:
$scope.removeCat = function (index) {
$scope.cats.splice(index,1);
}
or pass the whole item and use indexOf (the saver way)
<button class=" close-button" ng-click="removeCat(category)">
$scope.removeCat = function (item) {
$scope.cats.splice(myArray.indexOf(item), 1);
}
You can pass the index of the item you want to delete in the ng-click function:
<div class="cat-button" ng-repeat="category in cats" category="category">
<button class=" close-button" ng-click="removeCat($index)">
<span class="glyphicon glyphicon-remove-sign" aria-hidden=true> </span> </button>{{category.name}}
</div>
Then you can use this in your Angular controller like this:
$scope.removeCat = function (index) {
$scope.cats.splice(index, 1);
};
Update
Incase you don't want to pass in the index, instead you can also pass in the entire object and locate the index in your controller. The code below is setup to work on all browsers. (Just haven't tested it ;) )
$scope.removeCat = function (cat) {
// Using underscore
var index = _.indexOf($scope.cats, cat);
// Or using a for loop
for(var i = 0; i < $scope.cats.length; i++) {
//Assuming your cat object has an id property
if($scope.cats.id === cat.id) {
index = i;
break;
}
}
};
Or any other way to locate the index of an object in an array.
ng-click="removeCat(category)"
$scope.removeCat = function (categoryToDelete) {
var index = $scope.cats.indexOf(categoryToDelete);
$scope.cats.splice(index, 1);
};
Related
I am only posting the necessary code and solving this much will clear rest of my doubts. I am new to angularjs, so kindly forgive if I am asking something stupid.
I am using ng-repeat to generate a list which uses an array defined in the controller scope. When I click on 'Add Another' button, a new element is created. I want to get access of this element to add a class to it. But when I use 'getElementById' function in the same function 'addNewForm' I get 'null'.
However, when I call function 'fn' by hitting 'Find Untitled' button, I get the correct element. Could anybody explain and solve this? Any help is appreciated. Thanks in advance!
I am posting the code below:
HTML:
<div ng-controller="myctrl3">
<ul id ="menu_Ul">
<li ng-repeat="x in list">
<button id="{{ 'navAppsButtonID-' + $index }}">{{x}}</button>
<br>
</li>
<li>
<button ng-click="addNewForm()">Add another</button>
</li>
</ul>
<button ng-click="fn()">Find Untitled</button>
</div>
JS:
.controller("myctrl3", function($scope) {
var list = ['abcd', 'efgh', 'ijkl', 'mnop'];
$scope.list = list;
$scope.abc = function () {
var listPush = function () {
$scope.list.push("Untitled Menu");
for(var i = 0;i<$scope.list.length-1;i++) {
var element = document.getElementById('navAppsButtonID-'+i);
element.classList.remove('current');
}
};
var listLen = $scope.list.length;
if($scope.list[listLen-1] === undefined) {
listPush();
}
else if ($scope.list[listLen-1] == "Untitled Menu") {
alert("Cannot open more than one Untitled Menu at the same time.");
}
else {
listPush();
}
};
$scope.addNewForm = function() {
$scope.abc();
console.log("Element is: ", document.getElementById('navAppsButtonID-'+($scope.list.length-1)));
};
$scope.fn = function () {
console.log("Element is: ", document.getElementById('navAppsButtonID-'+($scope.list.length-1)));
};
})
You're thinking too much jQuery and too little angular. If the goal is to add a class to the last element of ng-repeat, this is how you do that:
<li ng-repeat="x in list">
<button ng-class="{ current: $last }">{{ x }}</button>
</li>
$last is a variable available inside ng-repeat, and if it's true, ng-class will set the class current on the element.
You don't assign unique ids to elements to getElementById from somewhere else when working in angular.
i'm using fabric js and trying to remove group of items when try to remove the parent item of group. following is my code.
jQuery(document).on('click', ".deleteBtn", function () {
if (canvas.getActiveObject()) {
var product_id = canvas.getActiveObject().get('product_id');
}
var canvasObj = canvas.getObjects();
for(var i = 0; i < canvasObj.length; i++){
var objRef = canvasObj[i];
var accessoryId = objRef.get('accessory_product_id');
var product_type = objRef.get('product_type');
if(accessoryId == product_id && product_type == "accessory"){
canvas.remove(objRef);
}
}
});
code is actually working, but not removing all items with same accessoryId and product_type parent item which is the active object trying to remove and two other items are removing properly. only two items left on canvas. there are all 5 items in group. those are images. i'm unable to find the issue please help. thanks!
HTML code
<div id="content-tab-3" class="visualiser-product-category content-tab active">
<ul>
<li>
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter_Spice.png" class="visualizer-product-img" alt="Placeholder" data-quantity="1" data-product_type="parent" data-product_id="343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Desk-Floral.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Garland.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Tabletop.jpg" class="hide accessory-343">
<img src="http://localhost/green_live/wp-content/uploads/2016/07/Winter-Spice-Wreath.jpg" class="hide accessory-343">
</li>
</ul>
</div>
Hello i noticed on your code that you try to get the active's object id, but no matter if there is active object or not you proceed to the loop, to delete the objects!!
Maybe, that causes the problem.
I'm going to show an example with forEach() function, but proceed to delete objects ONLY if there is active object:
jQuery(document).on('click', ".deleteBtn", function () {
//only if there is active object, do i delete objects
if (canvas.getActiveObject()) {
//get productId of active object
var product_id = canvas.getActiveObject().product_id;
//loop on the canvas objects
canvas.getObjects().forEach(function (object) {
if(object.accessoryId == product_id && object.product_type == "accessory"){
canvas.remove(object);
}
});//end forEach
}//end if
});//end 'click'
Hope helps, good luck.
I have my controller in Angular which contains an array and a delete method
function($scope, $http){
$scope.arrayOfObjects = [];
$scope.remove = function(obj){
var i = $scope.arrayOfObjects.indexOf(obj);
if( i > -1 ){
$scope.arrayOfObjects.splice(i, 1);
}
}
// Some other things
}
HTML
<a href ng-repeat="(key, obj) in arrayOfObjects track by $index">{{obj.id}}
<button type="button" role="button" class="btn btn-default" ng-click="remove(obj)">
<i class="fa fa-trash"></i>
<span>Delete</span>
</button>
</a>
Now all works well when I delete an object other than the last. When the user presses on the delete button for the last object, the page gets redirected to localhost:3000/# which is not mapped to anything and I get a blank page.
Has anyone encountered such behavior?
While the other answers are addressing your link / redirect issue, which would be solved by not having additional clickable items inside an anchor tag, the bigger problem is that you're using the wrong syntax for iterating over the objects of an array.
To iterate over an array you want this:
ng-repeat="obj in arrayOfObjects"
The syntax you're using is for iterating over the properties of one single object. Where key and value are the arguments passed to your repeater
ng-repeat="(key, value) in object"
Most likely what you want is something like this:
<div ng-repeat="obj in arrayOfObjects">
{{obj.id}}
<button ng-click="remove(obj)">Delete</button>
</div>
codepen
You can use 'filter' to return to original scope all itens that you want, just like that:
$scope.remove = function (objs) {
$scope.objs = objs.filter(function (obj) {
//Here you remove the item you do not want
return obj;
});
};
Html:
<button class="btn btn-danger btn-block" ng-click="remove(objs)">Delete</button>
Last element can be removed by using pop() and returns that element like $scope.arrayOfObjects.pop()
angular.module('app', [])
.controller('mycontroller', function($scope) {
$scope.arrayOfObjects = [{ id: 1 }, { id: 2 }, { id: 3 }]
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="mycontroller">
<button ng-click="arrayOfObjects.pop()">remove in inline</button>
<ul>
<li ng-repeat="myobj in arrayOfObjects">{{myobj.id}}</li>
</ul>
</div>
I'm building an app using AngularJS and LocalStorage. I've run into a problem that it's a tad too complex for me.
I have a list of people, and the idea is to be able to add arrays of names. I choose X names, click add, creates an object in an array, it resets the list, and I can start over, choose X names, click add, etc.
Here's how I create the temporary array that then I push into LocalStorage:
HTML:
<form>
<div class="col-md-3" ng-repeat="staff in stafflist | orderBy: 'name'">
<button class="btn form-control" ng-show="!staff.chosen" ng-click="pushStaff(staff)">{{staff.name}}</button>
<button class="btn btn-primary form-control" ng-show="staff.chosen" ng-click="unpushStaff(staff)">{{staff.name}}</button>
</div>
<button class="btn ng-click="addRecord()">Add passangers</button>
</form>
JS:
$scope.paxlist = [];
$scope.pushStaff = function (staff) {
staff.chosen = true;
$scope.paxlist.push(staff);
console.log($scope.paxlist);
};
$scope.unpushStaff = function (staff) {
staff.chosen = false;
var index=$scope.paxlist.indexOf(staff)
$scope.paxlist.splice(index,1);
console.log($scope.paxlist);
}
My problem is that I can create objects into the array, but when I add an object, the selected items of the list of names won't reset, so they will be pre-selected when adding the next object.
At the same time, it will also stay linked to the last object added, so when I modify the selection, the last object will also get modified.
This also messes with the possibility of adding an editing capability for each object of the array.
I've created a Plnkr that illustrates the issue.
If you could shed some light on the issue, that would be brilliant.
In addRecord you need reset property chosen
$scope.addRecord = function () {
$scope.recordlist.push({ pax: angular.copy($scope.paxlist) });
jsonToRecordLocalStorage($scope.recordlist);
$scope.editItem = false;
$scope.paxlist = [];
$scope.stafflist.forEach(function (el) {
el.chosen = false;
});
};
Demo: http://plnkr.co/edit/vV8OuKiTKYkFyy7SrjOS?p=preview
I'm writing an app in Angular and have something like this:
$scope.items = [
{'name':'someName',
'title': 'someTitle',
'filter': function(item){
Filters.setTableTitle(this.title); //cannot get title
...
}
},
{'name':'someName',
'title': 'someTitle',
'filter': function(item){
Filters.setTableTitle(this.title);
...
}
}
];
An array of objects. Part of each object is a function, and inside the function I would like to call a function that grabs the title of that object itself in order to pass it into a greater scope for the rest of the app.
However, I can't grab the title for each object.
How would I access the title in order to use it here?
Thanks.
Update
Here is my HTML that uses (something very similar to) the code above. I'm using the code to create buttons.
<p ng-repeat="link in items">
<block class="button" href="{{link.URL}}" title="{{link.title}}">
<a class="hrefLink" href="{{link.URL}}" ng-click="Filters.setFilter(link.filter, link.title)">
{{link.name}}
</a>
</block>
</p>
The function held within the filter part of each object returns information that is then passed into Filters.setFilter() which updates the DOM.
Filters.setFilter()
service.setFilter = function(filter, title){
service.searchTerm = '';
$spMenu.hide(); //close nav if open
service.selectedFilter = filter;
service.setTableTitle(title); //this does the job
};
I've rearranged the ways these functions work, and now simply pass in the title to the different functions. This gets the job done for what I want, but still could never solve the initial question at hand--how would I access part of an object from inside the object?
I don't know Angular wery well so there could definitely be a much better soultion.
If you call the function yourself, just write it like this:
$scope.items[x].filter(item);
If it's called somewhere else and this doesn't contain the right object, you can enumerate all objects and bind the function to it:
for (var i = 0; i < $scope.items.length; ++i) {
var item = $scope.items[i];
item.filter = item.filter.bind(item);
}
Edit:
You have two choices. First you can just bind the function in HTML:
<p ng-repeat="link in items">
<block class="button" href="{{link.URL}}" title="{{link.title}}">
<a class="hrefLink" href="{{link.URL}}" ng-click="Filters.setFilter(link.filter.bind(link))">
{{link.name}}
</a>
</block>
</p>
Or you can edit the function to do it for you:
<p ng-repeat="link in items">
<block class="button" href="{{link.URL}}" title="{{link.title}}">
<a class="hrefLink" href="{{link.URL}}" ng-click="Filters.setFilter(link)">
{{link.name}}
</a>
</block>
</p>
service.setFilter = function(link){
service.searchTerm = '';
$spMenu.hide(); //close nav if open
service.selectedFilter = link.filter.bind(link);
};