How to remove object from array within ng-repeat with AngularJS? - angularjs

I am having an array with objects like [{...}, {...}] which I am outputting with ng-repeat. Then I have a delete button with a function to delete it.
Is there a simple way to delete it in AngularJS, perhaps with $index? Or I need to specify an ID on every object as an property?

If you don't apply a filter to reorder or filter your array, you can do this:
<div ng-repeat="item in items" ng-click="delete($index)">{{item}}</div>
And the delete function:
$scope.items = [...];
$scope.delete = function (index) {
$scope.items.splice(index, 1);
}
Another way to do it without filter problems: (ONLY IE9+)
<div ng-repeat="item in items | orderBy: 'id'" ng-click="delete(item)">{{item}}</div>
And the delete function:
$scope.items = [...];
$scope.delete = function (item) {
$scope.items.splice($scope.items.indexOf(item), 1);
}
http://jsfiddle.net/oymo9g2f/2/

Here is another example, using Jade too:
template.jade:
label All Items
ul.list-group
li.list-group-item(ng-repeat="item in items | orderBy: '_id'")
strong {{item.name}}
a.trash(ng-click='deleteItem(item)')
//a.trash is a bootstrap trash icon, but you don't need to use it.
controller.js:
$scope.deleteItem = function (item) {
$scope.items.splice($scope.items.indexOf(item),1);
}

removeWith
comparison for each element in a collection to the given properties object,
returning an array without all elements that have equivalent property values.
$scope.collection = [
{ id: 1, name: 'foo' },
{ id: 1, name: 'bar' },
{ id: 2, name: 'baz' }
]
<tr ng-repeat="obj in collection | removeWith:{ id: 1 }">
{{ obj.name }}
</tr>
<tr ng-repeat="obj in collection | removeWith:{ id: 1, name: 'foo' }">
{{ obj.name }}
</tr>

First try to do it this way, but the listing was not actualized at runtime.
$scope.delete = function (index) {
delete $scope.items[index];
}
Then with the answer given above by Facundo Pedrazzini did work properly for me.
$scope.delete = function (index) {
$scope.items.splice(index, 1);
}
Version: AngularJS v1.6.4

In blade.php
<table style="width:100%;">
<tr ng-repeat="name in planFormData.names track by $index">
<td>
<div class="form-group">
<label>Plan Name<span style="color:red;">*</span> </label>
<input type="text" class="form-control" ng-model="planFormData.names[$index].plan_name" name="plan_name" id="status-name" placeholder="Plan Name" autocomplete="off" required>
</div>
</td>
<td>
<i class="icon-plus" ng-click="addRow($index)" ng-show="$last"></i>
<i class="icon-trash" ng-click="deleteRow($event,name)" ng-show="$index != 0"></i>
</td>
</tr>
</table>
In controller.js
$scope.deleteRow = function($event, name) {
var index = $scope.planFormData.names.indexOf(name);
$scope.planFormData.names.splice(index, 1);
};

In Angular 6, I did similar for Multi Dimensional Array. It's working
RemoveThisTimeSlot(i: number, j: number) {
this.service.formData.ConsultationModelInfo.ConsultationWeekList[i].TimeBlockList.splice(j, 1);
}

Related

What triggers a function call in other column when ngmodel changes in first column?

Consider the snippet:
JS
var mod = angular.module('module', []);
mod.controller('controller', function($scope) {
$scope.items = [{
id: 1,
label: 'aLabel',
subItem: {
name: 'aSubItem'
}
}, {
id: 2,
label: 'bLabel',
subItem: {
name: 'bSubItem'
}
}]
$scope.getValue = function(ngmodel) {
// some code goes here...
}
});
HTML
<body ng-controller='controller'>
<div>
<table>
<tr ng-repeat='count in counter'> // 5 times
<td>
<select ng-options="item.id as item.label for item in items"
ng-model="selected[$index]">
</select>
</td>
<td>
{{getValue(1)}}
</td>
<td>
</td>
</tr>
</table>
</div>
</body>
As soon as I select some value from the dropdown (select tag) in the first column, I notice that the function in the second column is triggered? What is the reason for this? What exactly is happening behind the scenes?
The reason is you are doing it inside ng-repeat
<tr ng-repeat = 'count in counter'>
You need to pass the object on the controller, in order to do some action on the same.
{{getValue(obj)}}

AngularJS - orderBy value when ng-repeat by key, value pair

I have counted the ocurrences of each item in a set of data with countBy function in lodash, and the result is this:
$scope.colors= {
"Orange": 3,
"Blue": 2,
"Pink": 1,
"Red": 1,
"Black": 2,
};
Now I would like to display the data and order it by its value. I've tried with
<div ng-controller="myCtrl" ng-app="myApp">
<ul>
<li ng-repeat="(key,value) in colors | orderBy:value">
{{key}} ({{value}})
</li>
</ul>
</div>
But the orderBy filter doesn't seem to do the trick (see the plunkr here)
Is there any way to do it with the current data form, or is it a better way to structure the data in order to achieve the desired result? Thanks in advance!
As the documentation says, orderBy expects an array as input, not an object. In general, although it's supported, I've never met a use-case where using an object with ng-repeat was a good idea.
Just transform your object into an array:
$scope.colors = [];
angular.forEach(occurrences, function(value, key) {
$scope.colors.push({
color: key,
count: value
});
});
and then use
<li ng-repeat="element in colors | orderBy:'count'">
{{ element.color }} ({{ element.count }})
</li>
See your updated plunkr.
After multiple tries, I found a way to iterate an object and have it ordered by the key.
<div ng-repeat="key1 in keys(obj1) | orderBy: key1">
I would instead use an array like so:
colors = [{color: 'red', value: 1}, {color: 'blue', value: 2}]
Then you can use
ng-repeat="color in colors | orderBy:'value'"
Plunkr
different approach - for
string from JsonConvert.SerializeObject(DataTable), so basically List<Dictionary<string, string>>
Example is combination of few solutions (sorry for no references)
In AngularJs controller:
vm.propertyName = '\u0022Spaced Column Name\u0022';
vm.reverse = true;
vm.sortBy = function (propertyName) {
vm.reverse = (vm.propertyName === '\u0022' + propertyName +'\u0022') ? !vm.reverse : false;
vm.propertyName = '\u0022' + propertyName + '\u0022';
};
vm.Data = JSON.parse(retValue.Data);
for (var i = 0; i < vm.Data.length; i++) {
var obj = {};
angular.forEach(vm.Data[i], function (value, key) {
obj[key] = value;
});
vm.DataArr.push(obj);
}
By ng-if="key != 'Id'" I'm hiding Id column with Guid
And then in html:
<table border="1">
<tr>
<td ng-repeat="(key, value) in vm.Data[0]" ng-if="key != 'Id'">
<button ng-click="vm.sortBy(key)">{{key}}</button>
<span ng-show="vm.propertyName == '\u0022'+key+'\u0022' && !vm.reverse" class="fa fa-arrow-up"></span>
<span ng-show="vm.propertyName == '\u0022'+key+'\u0022' && vm.reverse" class="fa fa-arrow-down"></span>
</td>
</tr>
<tr ng-repeat="row in vm.DataArr |orderBy:vm.propertyName:vm.reverse track by $index" ng-init="rowInd0 = $index">
<td ng-repeat="(key, value) in vm.Data[0]" ng-if="key != 'Id'">
<span>{{row[key]}}</span>
</td>
</tr>
</table>

Select All directive in AngularJS

I am using Checklist model directive with my App. I have issue, if -
I click select all button though it write up the array but its not
selecting checkbox. Same issue with Uncheck All though it empty the
model but it doesn't uncheck checkboxes.
If I select 2 or 3 randomly checkbox and click Select All Button it doesn't select All check-boxes.
Though its writing values to pushArray. But issues are checking and unchecking checkboxes.
$scope.items = [{id:1, name:"abc"},{id:2, name:"def"},{id:3, name:"ghi"}];
$scope.pushArray = [];
<table>
<tr ng-repeat="e in items">
<td class="text-right">
{{e.id}}
<input type="checkbox" checklist-change="imChanged()" checklist-model="pushArray" checklist-value="e.id" >
</td>
</tr>
</table>
I think you are pushing the complete list of object which is wrong. You just need to map the list and pass the id to the $scope
Edit: Works fine when you use $scope.pushArray as an object instead of array.
Working Plnkr
HTML
<body ng-controller="selection">
<table>
<tr ng-repeat="e in items">
<td>
<input type="checkbox" checklist-model="pushArray.ids" checklist-value="e.id"> {{e.name}}
</td>
</tr>
</table>
{{pushArray.ids | json}}
<br />
<button ng-click="select_all();">Select All</button>
<button ng-click="unselect_all();">Unselect All</button>
</body>
JS
var app = angular.module('app', ["checklist-model"]);
app.controller('selection', ['$scope', function($scope) {
$scope.items = [{
id: 1,
name: "abc"
}, {
id: 2,
name: "def"
}, {
id: 3,
name: "ghi"
}];
$scope.pushArray = { ids: []}; // Works fine when using it as an object
//$scope.pushArray = [];
$scope.select_all = function() {
$scope.pushArray.ids = $scope.items.map(function(item) { return item.id; });
};
$scope.unselect_all = function() {
$scope.pushArray.ids = [];
};
}]);
Hope it works for you!
I updated the examples on checklist-model and fix this issue. Check them out http://vitalets.github.io/checklist-model/

Angular update object in array

I wanna update an object within an objects array. Is there another possibility than iterating over all items and update the one which is matching? Current code looks like the following:
angular.module('app').controller('MyController', function($scope) {
$scope.object = {
name: 'test',
objects: [
{id: 1, name: 'test1'},
{id: 2, name: 'test2'}
]
};
$scope.update = function(id, data) {
var objects = $scope.object.objects;
for (var i = 0; i < objects.length; i++) {
if (objects[i].id === id) {
objects[i] = data;
break;
}
}
}
});
There are several ways to do that. Your situation is not very clear.
-> You can pass index instead of id. Then, your update function will be like:
$scope.update = function(index, data) {
$scope.object.objects[index] = data;
};
-> You can use ng-repeat on your view and bind object properties to input elements.
<div ng-repeat="item in object.objects">
ID: <input ng-model="item.id" /> <br/>
Name: <input ng-model="item.name" /> <br/>
</div>
Filters that help in finding the element from the array, can also be used to update the element in the array directly.
In the code below [0] --> is the object accessed directly.
Plunker Demo
$filter('filter')($scope.model, {firstName: selected})[0]
Pass the item to your update method. Take a look at sample bellow.
function MyCtrl($scope) {
$scope.items =
[
{name: 'obj1', info: {text: 'some extra info for obj1', show: true}},
{name: 'obj2', info: {text: 'some extra info for obj2', show: false}},
];
$scope.updateName = function(item, newName){
item.name = newName;
}
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app>
<table ng-controller="MyCtrl" class="table table-hover table-striped">
<tr ng-repeat="x in items">
<td> {{ x.name }}</td>
<td>
Update
<div ng-show="showUpdate" ><input type="text" ng-model="someNewName"> <input type="button" value="update" ng-click="updateName(x, someNewName); showUpdate = false;"></div>
</td>
</tr>
</table>
</body>
Going off your plunker, I would do this:
Change
Edit
to be
Edit
Then use the array index within your $scope.selectSubObject method to directly access your desired element. Something like this:
$scope.selectSubObject = function(idx) {
$scope.selectedSubObject = angular.copy(
$scope.selectedMainObject.subObjects[idx]
);
};
If however, you only have the id to go off of, then you can use the angular filterService to filter on the id that you want. But this will still do a loop and iterate over the array in the background.
See angularjs documentation for ngrepeat to see the variables that it exposes.

update fields in ngRepeat based on another field in same index

I want to be able to populate a text input field inside an ng-repeat loop with the value of another field inside that same loops index when I click a button.
JSFiddle of what I have so far: http://jsfiddle.net/3FKMx/
When the Copy Names button is clicked I want each text box to be populated with the same value that's in the array. Currently it populates them all with the value of the last item in the array.
Controller:
var app = angular.module('myApp', []);
function someController($scope) {
$scope.names = ["name1","name2","name3"];
$scope.copyNames = function() {
angular.forEach($scope.names,
function (value){
$scope.newName = value;
}
);
};
}
Template:
<div ng-controller="someController">
<button class="btn btn-primary" ng-click="copyNames()">Copy Names</button>
<table>
<tr ng-repeat="name in names">
<td>{{name}}</td>
// I want to populate this input with {{ name }} when I click the button above.
<td><input type="text" ng-model="newName"/></td>
</tr>
</table>
</div>
Solution 1
With an updated data structure it's a bit nicer for looping through.
Solution 2
Create a new array to store the values. Set them by key and look them up by key in your curly braces.
html
<div ng-controller="someController">
<button class="btn btn-primary" ng-click="copyNames()">Copy Names</button>
<table>
<tr ng-repeat="name in names">
<td>{{name}}</td>
<td><input type="text" ng-model="models[name]"/></td>
</tr>
</table>
</div>
JavaScript
var app = angular.module('myApp', []);
function someController($scope) {
$scope.names = ["name1","name2","name3"];
$scope.models = {};
$scope.copyNames = function() {
angular.forEach($scope.names,
function (value, key) {
$scope.models[value] = value;
}
);
};
}
DEMO (updated your fiddle) is what you are looking for?
Tried using an object to hold the label and model:
$scope.names = [{label: "name1", model: ''},
{label: "name2", model: ''},
{label: "name3", model: ''}];
//Also using jQuery.each to break from the loop
//once we know which value to copy
$scope.copyNames = function() {
$.each($scope.names,
function (i, value){
if(value.model) {
angular.forEach($scope.names, function(name){
name.model = value.model;
});
//Break the loop if done copying
return false;
}
}
);
};
Note: jQuery is used as an external library which will be available in angular as is.

Resources