Remove a row on ng-click using angularJs - javascript

I have a table with the default empty row(Row further includes a columns with different functionalities).Dynamically a multiple rows can be added by click of a button as per the requirement.i want to remove a row when i click a remove-icon from the same-row(remove-icon included in one of the column).
<td class="text-right"> <a href="" class="remove-service" ng-click="vm.removeService(service,true)">
<img src="images/delete.png"></a>  </td>
i have a above column to be included in all rows.whenever i click on remove-icon from any of the rows.(i want to remove a particular row from which icon is clicked)
vm.removeService = function (service, removeService) {
}
Here,is the ng-repeat code for the row.
<tr class="bx--table-row" ng-repeat="service in vm.servicesWithCountries track by $index">
vm.servicesWithCountries = [{ serviceName:"", countries: []}];

Hi you can do like below : Assuming your ng-repeat object will be like somewhat mention below.
<table>
<tr ng-repeat="item in items | orderBy: 'id'">
<td>
<span>
Hello, {{item.name}}!
</span>
</td>
<td>
Delete
</td>
</tr>
</table>
and in Controller :
$scope.items = [{
name: 'item 1',
id: '4'
}, {
name: 'item 2',
id: '3'
}, {
name: 'item 3',
id: '2'
}, {
name: 'item 4',
id: '1'
}];
$scope.delete = function(item) {
$scope.items.splice($scope.items.indexOf(item), 1);
}
refer this fiddle for complete code

You can use splice and indexOf on your service
<tr class="bx--table-row" ng-repeat="service in vm.servicesWithCountries track by $index">
<td class="text-right"> <a href="" class="remove-service"
ng-click="vm.removeService(service, true)">
<img src="images/delete.png"></a>  </td>
</tr>
Like:
ng-click="vm.removeService(service,true)"
JS
vm.removeService = function(service, removeService) {
if(removeService === true){
var index = vm.servicesWithCountries.indexOf(service);
vm.servicesWithCountries.splice(index, 1);
}
}

Related

how to count items in nested ng-repeat without $index

I want to count iteration of ng-repeat, when condition match.
I've tried $index but it print for all itration/items in nested ng-repeat
Fiddle link :https://jsfiddle.net/gdr7p1zj/1/
<tbody ng-controller="MainCtrl">
<tr ng-repeat-start="a in test1">
<td>{{a.categoryName}}(count_here)</td>
</tr>
<tr ng-repeat-end ng-repeat="b in test" ng-if="a.categoryId==b.categoryId">
<td>{{b.name}}</td>
</tr>
</tbody>
i want like this
category_one(4) <=item count 4 items in this category so 4 will display
item1
item2
item3
item4
category_two(2)
item5
item6
<!-- this is in controller -->
$scope.test1=[{
categoryId:'1',categoryName:'category one'
},
{
categoryId:'2',categoryName:'category two'
}]
$scope.test = [
{categoryId:'1',name:'cate 1 elem0'},
{categoryId:'1',name:'cate 1 elem1'},
{categoryId:'2',name:'cate 2 elem'}
];
});
An option is to create a function (getCount) in the controller which do the count, something like this:
$scope.getCount = function(categoryId) { // returns the count by matching by categoryId
return $scope.test.filter(function(element) { // first, filter elements in `test`
return element.categoryId === categoryId; // matching by categoryId
}).length; // then, return the count of how many results we got after the filter
}
And in the html call that function like this:
<tbody ng-controller="MainCtrl">
<tr ng-repeat-start="a in test1">
<td>{{a.categoryName }} ({{getCount(a.categoryId)}})</td> <!-- <-- call the function in order to display the count -->
</tr>
<tr ng-repeat-end ng-repeat="b in test" ng-if="a.categoryId == b.categoryId">
<td>{{b.name}}</td>
</tr>
</tbody>
See a demo here: https://jsfiddle.net/lealceldeiro/v9gj1ok4/11/
Thanks for your help. But i get expected output without any functions call or filters
Here fiddle Link: https://jsfiddle.net/wk3nzj96/
htmlCode:
<div ng-app='myapp' >
<div ng-controller="MainCtrl">
<table ng-init="$scope.counter=0">
<tr ng-repeat-start="cate in mainCategory">
<td> {{cate.name}} ({{$scope.counter[$index]}})</td></tr>
<tr ng-repeat="itemsItr in items" ng-init="$scope.counter[$parent.$parent.$index]=$scope.counter[$parent.$parent.$index]+1" ng-if="itemsItr.mid==cate.id">
<td>{{itemsItr.name}}</td>
</tr>
<tr ng-repeat-end ng-if="false"></tr>
</table>
</div>
</div>
and ControllerCode:
(function() {
angular.module('myapp', []).controller('MainCtrl', function($scope) {
$scope.mainCategory = [
{ name: "categoryOne",id:1 },
{ name: "categoryTwo",id:2 }
];
$scope.items = [
{ name: "item1FromCateOne" ,mid:1 },
{ name: "item2FromCateOne",mid:1 },
{ name: "item3FromCateOne" ,mid:1 },
{ name: "item1FromCateTwo",mid:2 }
];
});
Is this Standard way to do this?

Creating a multilevel grid with angular

I have a requirement where I need to create a multi level grid. Where when user clicks on checkbox a child grid will be opened. Please look at HTML shown below:
<table>
<thead>
<tr>
<th>check</th>
<th>Result</th>
</tr>
</thead>
<tbody>
<tr>
<td><label class="checkbox"><input type="checkbox"><a>test</a></label></td>
<td> Description</td>
</tr>
<tr>
<td colspan="12">
<table>
<tr>
<td><label class="checkbox"><input type="checkbox"><a>testing</a></label></td>
<td>description</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
Something similar as shown here: http://dojo.telerik.com/uQEx.
I have written angular code for it. And I have wrapped tr in *ngfor to show high level. Please look at code shown below:
<tr *ngFor = "let data of values">
<td>
<label class="checkbox">
<input type="checkbox">
</label>
<a (click) = "getTerms(data.id)">{{data.id}}</a>
</td>
<td>{{data.desc}}</td>
</tr>
I need to append another list when I click on a tag that is data.id. I am confused how to append response of sub terms in html. Please let me know if you have any suggestion. Also I don't want to use any plugin for it.
EDIT:
The response I am getting on page load is:
[
{id:1, desc:'test', level: 0},
{id:2, desc:'testing',level: 0}
]
And now when I click on id =1 column I am sending service request:
/get/Term/1
And I am getting response:
[ {id:5, desc: 'test test', level: 1} ]
In the similar way now if I click on id=5 I will get response as:
[ {id:8, desc: 'test test test', level: 2} ]
Hope now its clear.
Tavish the question is: What do you have? What do you want obtain?
...
As you are add items to your data, one idea is that
At first you have
this.data=[
{id:1, desc:'test', level: 0},
{id:2, desc:'testing',level: 0}
]
If click "1" you received
[ {id:5, desc: 'test test', level: 1} ]
It's good that you change your data adding "children". So in getData(data.id,i)
//we pass as argument the index too
getData(id:number,index:number)
{
this.httpClient.get("url"+id).subscribe(res=>{
this.data[index].children=res
}
}
So, your data becomes
this.data=[
{id:1, desc:'test', level: 0,children:
[ {id:5, desc: 'test test', level: 1} ]
},
{id:2, desc:'testing',level: 0}
]
Now you only need to using two *ngFor
<div *ngFor="let level0 of data;let index=i">
{{level0.id}}{{level0.desc}}{{level0.level}}
<button (click)="getData(level0.id,index)">click</button>
<div *ngFor="let level1 of level0.children">
{{level1.id}}{{level1.desc}}{{level1.level}}
</div>
</div>
This idea work if you need fews levels, but if you have more that two or three levels can be a nightmire
With more levels you need, when received the data push in data but add the id_parent
getData(id:number)
{
this.httpClient.get("url"+id).subscribe(res=>{
res.forEach(x=>{
//¡¡IMPORTANT!! not {parent.id,..x}
this.data.push({...x,parent:id})
})
})
}
So, your data becomes
this.data=[
{id:1, desc:'test', level: 0}
{id:2, desc:'testing',level: 0}
{id:5, desc: 'test test', level: 1,parent:1}
]
if you have a function like
listData(parent:number)
{
return (parent)? this.data.filter(x=>x.parent==parent)
: this.data.filer(x=>!x.parent)
}
Your *ngFor can be like
<div *ngFor="let level0 of data;let index=i">
{{level0.id}}{{level0.desc}}{{level0.level}}
<button (click)="getData(level0.id)">click</button>
<div *ngFor="let level1 of listData(level0.id)">
{{level1.id}}{{level1.desc}}{{level1.level}}
</div>
</div>
Example to show a "iterate" component
//app.component
#Component({
selector: 'app-root',
template:`
<app-app-children [children]="data"></app-app-children>
`
})
export class AppComponent {
title = 'app';
isdisabled:boolean=false;
data=[{id:1},
{id:2,
children:[{id:4},{id:5},{id:6,
children:[{id:9},{id:10}]}]},
{id:3,
children:[{id:7},{id:8}]}
];
constructor(){}
}
//app-children
#Component({
selector: 'app-app-children',
template:`
<p>
app-children works!
</p>
<div *ngFor="let item of children">{{item.id}}
<div *ngIf="item.children">
<app-app-children [children]="item.children"></app-app-children>
</div>
</div>`
})
export class AppChildrenComponent {
constructor() { }
#Input() children
}
//If whe can have a table, We can change the template like:
#Component({
selector: 'app-app-children',
template: `
<table>
<thead>
<th>#</th>
</thead>
<tbody>
<tr *ngFor="let item of children">
<td>
<div>
{{item.id}}
</div>
<div *ngIf="item.children">
<app-app-children [children]="item.children"></app-app-children>
</div>
</td>
</table>
`,
styles:[`
table, th, td {
border: 1px solid black;
margin-left:2rem;
}
`
]
})

AngularJS - Trouble with ng-repeat

Here's the data I'm working with:
$scope.products = [
{
'id': 643,
'name': 'Product Name',
'applications': [
{
'id': 100,
'name': 'Adobe After Effects CC (2014)',
'gfx': [
{
'id': 514,
'name': 'Graphics AE Test 1'
}
]
},
{
'id': 101,
'name': 'Adobe Premiere Pro CC (2014)',
'gfx': [
{
'id': 514,
'name': 'Graphics AP Test 1'
},
{
'id': 512,
'name': 'Graphics AP Test 2'
}
]
}
]
}
];
What i'm trying to do is loop through all of the graphics card for a specific application. You choose the application via a dropdown, and I have the selected application in a variable {{ scope.selectedApplication }}. So with that, here's what I have tried:
<tr data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<td>{{ driver.gfx[$index].name }}</td>
</tr>
So this is somewhat working, just not exactly how I want. The filter is filtering it down to the correct application, which works fine. The problem I am having is that driver.gfx[$index].name is only showing the first result. Since I am looping through applications instead of gfx, the $index isn't going to work for me.
How can I loop through the graphics cards after my initial ng-repeat? It seems like I need two statements, but how would that work?
Am I going about this the wrong way?
you can have nested hg-repeat if you like to have a nested table.
<tr data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<td>
<table>
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
</table>
</td>
</tr>
if you want to have single denormalized table, one option would be to create a function that does the denormalization and then use result of that function in a normal hg-repeat.
The other option would be having multiple tbody. so your outer loop occurs on tbody and inner loop on row
<tbody data-ng-repeat="driver in result.applications | filter: { name: selectedApplication } track by $index">
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
</tbody>
and finally you can have some rows that either style them as separators or just hide them by CSS and use ng-repeat-start and hg-repeat-end like this
<table>
<tr class="separator" data-ng-repeat-start="driver in result.applications | filter: { name: selectedApplication } track by $index"><td></td></tr>
<tr ng-repeat="item in driver.gfx">
<td >
{{item.name}}
<td/>
</tr>
<tr class="seperator" ng-repeat-end><td></td></tr>
</table>
You need another ng-repeat that loops through each gfx.
<td>
<ul>
<li ng-repeat="gfx in driver.gfx">{{ gfx.name }}</li>
</ul>
</td>
Assuming the selected application is set via a binding of {{ selectedApplication }} ($scope is implied), then your ng-repeat should look like:
<tr data-ng-repeat="driver in selectedApplication | filter: { name: selectedApplication } track by $index">
<td>{{ driver.gfx[$index].name }}</td>
</tr>
This means you'll be talking about the driver inside the selected application object.

.after() in angularjs (nested ng-repeat recursive iteration)

I have a simple structure
function linksRarrange($scope) {
$scope.links = [
{
text: 'Menu Item 1',
url: '#',
},{
text: 'Menu Item 2',
url: '#',
submenu: [
{
text: 'Sub-menu Item 3',
url: '#',
},{
text: 'Sub-menu Item 4',
url: '#',
submenu: [
{
text: 'Sub-sub-menu Item 5',
url: '#',
},{
text: 'Sub-sub-menu Item 6',
url: '#',
}
]
}
]
},{
text: 'Menu Item 3',
url: '#',
}
];
}
I wish to build a table where the children are rendered in a row the children after the parent eg:
Menu Item 1
Menu Item 2
Sub-menu Item 3
Sub-menu Item 4
Sub-menu Item 5
Sub-menu Item 6
Menu Item 3
<table>
<thead>
<tr>
<th>Title</th>
<th>Url</th>
</tr>
</thead>
<tbody>
<tr>
<td>Menu Item 1</td>
<td>#</td>
</tr>
<tr>
<td>Menu Item 2</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 3</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 4</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 5</td>
<td>#</td>
</tr>
<tr>
<td>Sub-menu Item 6</td>
<td>#</td>
</tr>
<tr>
<td>Menu Item 3</td>
<td>#</td>
</tr>
</tbody>
</table>
I have looked at using ng-repeat-start and ng-repeat-end, but this doesn't support what I want to do.
Can anyone offer any help please?
If you are using this for navigation you can put it in a nested <ul> and us nice css to style it. something like:
<ul ng-repeat="menu in links">
<li>{{menu.text}}</li>
<ul ng-repeat="subs in menu.submenu">
<li>{{subs.text}}</li>
</ul>
<ul>
... something like that
Take a look at these resources:
https://groups.google.com/forum/#!msg/angular/TbpjE-5XEM0/yUi8wqc7sWoJ
http://sporto.github.io/blog/2013/06/24/nested-recursive-directives-in-angular/
I think the first example in the first link can be fitted to match your need.
This is definatly not the first time this question has been asked and I think you can find a lot more of these examples if not a direct hit at what you're looking for if you just google it up.
My current solution is not perfect, in fact the resulting html is not a table/tr but a set of nest ul/li elements that are then styled using css to emulate the design spec.
The causal factor is due to the problems with the placement of tbody an tr within a directive. If anyone has a workaround I would be very grateful for you to share this please.
The simple markup is as follows:
<menucollection menucollection='links'></menucollection>
Supported by 2 directives:
window.app.directive('menucollection', function () {
return {
restrict: "E",
replace: true,
scope: {
menucollection: '='
},
template: "<ul><menuitem ng-repeat='menuitem in menucollection' menuitem='menuitem'></menu></ul>"
}
});
window.app.directive('menuitem', function ($compile{
return {
restrict: "E",
replace: true,
scope: {
menuitem: '='
},
template: "<li>{{menuitem.Name}}</li>",
link: function (scope, element, attrs) {
scope.catMarker = attrs.marker;
scope.subcatMarker = attrs.marker + ' » ';
if (scope.menu.Children.length > 0) {
element.append('<menucollection menucollection="menu.submenu"></menucollection>');
$compile(element.contents())(scope);
}
}
};
});

Angularjs: How do I get the item in a list when using ngChange?

I'm trying to get the item that just changed in this small example, is there some kind of context I should use? I hoped it would be as simple as just referring to $this, but that doesn't seem to work.
<html ng-app>
<head>
<script src="https://code.angularjs.org/1.2.9/angular.min.js"></script>
<script>
function myController($scope) {
$scope.items = [
{ id: 1, name: "First" },
{ id: 2, name: "Second" },
{ id: 3, name: "Third" }
];
$scope.test = function() {
// How do I get the object in the list related to the change i did?
// I.e. "{ id: 2, name: "Second" }" for the second item.
};
}
</script>
</head>
<body>
<div ng-controller="myController">
<table>
<tbody ng-repeat="item in items">
<tr>
<td>{{ item.id }}</td>
<td><input type="text" ng-model="item.name" ng-change="test()"/></td>
</tr>
</tbody>
</table>
</div>
</body>
Take a look at this
Working Demo
html
<div ng-app='myApp' ng-controller="myController">
<table>
<tbody ng-repeat="item in items">
<tr>
<td>{{ item.id }}</td>
<td><input type="text" ng-model="item.name" ng-change="test(item.name)"/></td>
</tr>
</tbody>
</table>
</div>
script
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
$scope.items = [
{ id: 1, name: "First" },
{ id: 2, name: "Second" },
{ id: 3, name: "Third" }
];
$scope.test = function(item) {
alert(item);
};
});

Categories