I have an Angular SPA that features a cart (array) that users can add items to. I'd like to prevent the user from adding any particular item to the cart twice.
function CartForm($scope) {
$scope.products = [{
"description": "BB-8 Droid",
"qty": "1",
"cost": "99"
}, {
"description": "C-3PO Droid",
"qty": "1",
"cost": "499"
}, {
"description": "R2-D2 Astromech Droid",
"qty": "1",
"cost": "899"
}, {
"description": "R5-D4 Astromech Droid",
"qty": "1",
"cost": "899"
}, {
"description": "IG-88 Bounty Hunter Droid",
"qty": "1",
"cost": "899"
}];
$scope.invoice = {
items: []
};
$scope.addItem = function(product) {
$scope.invoice.items.push(product);
},
$scope.removeItem = function(index) {
$scope.invoice.items.splice(index, 1);
},
$scope.total = function() {
var total = 0;
angular.forEach($scope.invoice.items, function(item) {
total += item.qty * item.cost;
})
return total;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<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>
<h2>Shopping Cart Example</h2>
<div ng:controller="CartForm">
<table class="table">
<thead>
<th>Description</th>
<th>Qty</th>
<th colspan="2">Price</th>
</thead>
<tr ng-repeat="product in products">
<td>{{product.description}}</td>
<td>{{product.qty}}</td>
<td>{{product.cost | currency }}</td>
<td>
<button class="btn btn-danger" ng-click="addItem(product)">ADD TO CART</button>
</tr>
</table>
<table class="table">
<tr>
<th>Description</th>
<th>Qty</th>
<th>Cost</th>
<th>Total</th>
<th></th>
</tr>
<tr ng:repeat="item in invoice.items">
<td>
<input type="text" ng:model="item.description" class="input-small">
</td>
<td>
<input type="number" ng:model="item.qty" ng:required class="input-mini">
</td>
<td>
<input type="number" ng:model="item.cost" ng:required class="input-mini">
</td>
<td>{{item.qty * item.cost | currency}}</td>
<td>
[<a href ng:click="removeItem($index)">X</a>]
</td>
</tr>
<tr>
<td></td>
<td></td>
<td>Total:</td>
<td>{{total() | currency}}</td>
</tr>
</table>
</div>
See working JSFiddle here: http://jsfiddle.net/tedleeatlanta/22591h2y/15/
You can add some logic to your AddItem to deal with all of this.
This isn't the most elegant way, but will get you going in the right direction - Something like this works well:
$scope.addItem = function(product) {
var exist = false;
for(var i = 0; i < $scope.invoice.items.length;i++){
if ($scope.invoice.items[i].description==product.description)
{
// having to use parseInt here because your Qty isn't a number...naughty naughty
$scope.invoice.items[i].qty = parseInt($scope.invoice.items[i].qty)+1;
exist = true;
}
}
if (!exist)
$scope.invoice.items.push(product);
},
It increases the Qty if it already exists, or adds it if it doesn't
See it running here http://jsfiddle.net/22591h2y/16/
Or, for something that doesn't need to parseInt - change your objects qty to ints, rather than strings.
See this update http://jsfiddle.net/22591h2y/17/
Related
Functionality I want to implement is that when I click on "select All" checkbox, I want to push the selected item in new array and delete from current one.
Tried with splice function, but not able to delete all items from the first table.
enter code hereHere is the sample plnkr I have created, So when I click on "select All" from first table, all its items should get pushed in "New Table" and at the same time removed from "First table(named Old table)
This will clear your array and push all entries in $scope.merged
$scope.pushlist = function(data){
for(var item of data){
$scope.merged.push({"name":item.name});
}
data.length=0
};
Use angular.copy to make an copy of the object
var app = angular.module("myApp", []);
app.controller("SecondCtrl", function($scope) {
$scope.merged = [];
$scope.data = [{
"name": "ABC",
"selected": false
}, {
"name": "HJK",
"selected": false
}, {
"name": "PQR",
"selected": false
}, {
"name": "LMN",
"selected": false
}];
$scope.selectall = function(checkAll) {
if (checkAll) {
$scope.merged = angular.copy($scope.data);
$scope.data.length = 0;
} else {
$scope.data = angular.copy($scope.merged);
$scope.merged.length = 0;
}
};
});
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="myApp" ng-controller="SecondCtrl">
<div>
<h1>Old Table</h1>
<table>
<thead>
<th>
<input type="checkbox" ng-click="selectall(checkAll)" ng-model="checkAll">Select All</th>
<th>Name</th>
</thead>
<tbody>
<tr ng-repeat="item in data">
<td>
<input type="checkbox" ng-model="item.selected">
</td>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
</div>
<hr>
<div>
<h2>New Table</h2>
<table ng-show="merged">
<thead>
<th>Name</th>
</thead>
<tbody>
<tr ng-repeat="item in merged">
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
</div>
</div>
Fiddle Demo
I have dynamic result of an array which need to bind with table but some different layout using Angular JS. I have tried many attempt but no success. I have require desired result. Helps are definitely appreciated.
var arr = [
{
"unique_id": "CS",
"college": "BSCS",
"arr_length": 1,
"program_section": [
{
"question": "How you rate your teacher",
"total": 135,
},
{
"question": "Are you satisfy with your teacher",
"total": 142,
},
{
"question": "Which course you have most like throughout the session",
"total": 135,
},
{
"question": "How much you have rate your instructor",
"total": 137,
},
]
},
{
"unique_id": "MBA",
"college": "BBA",
"arr_length": 2,
"program_section": [
{
"question": "How you rate your teacher",
"total": 175,
},
{
"question": "Are you satisfy with your teacher",
"total": 142,
},
{
"question": "Which course you have most like throughout the session",
"total": 165,
},
{
"question": "How much you have rate your instructor",
"total": 137,
},
]
},
{
"unique_id": "CA",
"college": "Account",
"arr_length": 1,
"program_section": [
{
"question": "How you rate your teacher",
"total": 145,
},
{
"question": "Are you satisfy with your teacher",
"total": 162,
},
{
"question": "Which course you have most like throughout the session",
"total": 125,
},
{
"question": "How much you have rate your instructor",
"total": 117,
},
]
}
];
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$scope.names = arr;
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="customersCtrl">
<table border="1" ng-repeat="x in names">
<tr>
<td>Question</td>
<td>{{ x.college }}</td>
</tr>
<tr>
<td>
<table border="1" ng-repeat="y in x.program_section">
<tr>
<td width="100px">{{ y.question }}</td>
<td width="100px">{{ y.total }}</td>
</tr>
</table>
</td>
<td>
</tr>
</table>
</div>
Desired Result
<table width="200" border="1">
<tr>
<td>Question</td>
<td>CS</td>
<td>MBA</td>
<td>CA</td>
</tr>
<tr>
<td>How you rate your teacher</td>
<td>135</td>
<td>175</td>
<td>145</td>
</tr>
<tr>
<td>Are you satisfy with your teacher</td>
<td>142</td>
<td>142</td>
<td>162</td>
</tr>
<tr>
<td>Which course you have most like throughout the session</td>
<td>135</td>
<td>165</td>
<td>125</td>
</tr>
<tr>
<td>How much you have rate your instructor</td>
<td>137</td>
<td>137</td>
<td>117</td>
</tr>
</table>
You have to loop all elements for the table head and then again for your body. I used a fixed number to loop over your questions here. You can simply modify the filter, tho.
JSFiddle
HTML
<div ng-app="myApp" ng-controller="customersCtrl">
<table border="1">
<thead>
<tr>
<td>Question</td>
<td ng-repeat="x in names">{{ x.college }}</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="n in [] | range:4">
<td>
{{ names[0].program_section[n].question }}
</td>
<td width="100px" ng-repeat="x in names">
{{ x.program_section[n].total }}
</td>
</tr>
</tbody>
</table>
</div>
Javascript
var app = angular.module('myApp', []);
app.controller('customersCtrl', function($scope, $http) {
$scope.names = arr;
}).filter('range', function() {
return function(input, total) {
total = parseInt(total);
for (var i=0; i<total; i++) {
input.push(i);
}
return input;
};
});
I am facing one issue.I need to display some array of data inside table using Angular.js.I am explaining my code below.
Table:
<table class="table table-bordered table-striped table-hover" id="dataTable" >
<tbody>
<tr>
<td rowspan="2">Date</td>
<td rowspan="2">id</td>
<td rowspan="2">email</td>
<td colspan="7">Order</td>
</tr>
<tr>
<td>Order Id</td>
<td>Status</td>
</tr>
<tr>
<td></td>
<td></td>
<td></td>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>
I am explaining my array of data below.
$scope.listOfData=
[
{
"date": "2016-01-25 18:14:00 to 2016-02-05 11:26:05",
"id": "36",
"email": "raj#gmail.com",
"order": [
{
"order_status": 1,
"order_id": 1111
},
{
"order_status": 0,
"order_id": 2222
},
{
"order_status": 1,
"order_id": 5555
}
]
},
{
"date": "2016-01-23 13:15:59 to 2016-01-25 18:14:00",
"id": "37",
"email": "rahul#gmail.com",
"order": [
{
"order_status": 1,
"order_id": 3333
},
{
"order_status": 0,
"order_id": 4444
}
]
}
]
I need to display above data into the table using Angular.js.please help me.
Run this code and check out the output. Let me know if you need different format.. cheers!!!
var app = angular.module("myApp",[]);
app.controller("AppController",['$scope',AppController]);
function AppController($scope) {
$scope.listOfData=[
{
"date": "2016-01-25 18:14:00 to 2016-02-05 11:26:05",
"id": "36",
"email": "raj#gmail.com",
"order": [
{
"order_status": 1,
"order_id": 1111
},
{
"order_status": 0,
"order_id": 2222
},
{
"order_status": 1,
"order_id": 5555
}
]
},
{
"date": "2016-01-23 13:15:59 to 2016-01-25 18:14:00",
"id": "37",
"email": "rahul#gmail.com",
"order": [
{
"order_status": 1,
"order_id": 3333
},
{
"order_status": 0,
"order_id": 4444
}
]
}
];
}
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-app="myApp" ng-controller="AppController">
<table cellspacing="5px" style="border:1px solid black;">
<tr >
<th>Date</th>
<th>id</th>
<th>email</th>
<th>Order</th>
</tr>
<tr ng-repeat="orderInfo in listOfData">
<td>{{orderInfo.date}}</td>
<td>{{orderInfo.id}}</td>
<td>{{orderInfo.email}}</td>
<td>
<table>
<tr>
<th>Order stat</th>
<th>Id<th>
</tr>
<tr ng-repeat="orderStat in orderInfo.order">
<td>{{orderStat.order_status}}</td>
<td>{{orderStat.order_id}}</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
</body>
</html>
<!--
This is for table inside row.
<tr ng-repeat="orderInfo in listOfData">
<td>{{orderInfo.date}}</td>
<td>{{orderInfo.id}}</td>
<td>{{orderInfo.email}}</td>
<td>
<table>
<tr ng-repeat="orderStat in orderInfo.order">
<td>{{orderStat.order_status}}</td>
<td>{{orderStat.order_id}}</td>
</tr>
</table>
</td>
</tr> -->
Try this
<tr ng-repeat="(key,list) in listOfData">
<td ng-repeat="(key, lists) in list.order "> {{lists.order_status}}</td>
<td ng-repeat="(key, lists) in list.order "> {{lists.order_id}}</td>
</tr>
Make you header fixed of the table, put it outside of your loop.
Put this outside of the loop i.e ng-repeat
<tr>
<td rowspan="2">Date</td>
<td rowspan="2">id</td>
<td rowspan="2">email</td>
<td colspan="7">Order</td>
</tr>
You don't want to create it for every item, as it's going to be fixed.
Now, iterate through your list of json objects, using ng-repeat, as explained above.
Something like this..
<table class="table table-bordered table-striped table-hover" id="dataTable" >
<div ng-repeat="list in listOfData">
{{list.id}}
<div ng-repeat="oderlist in list.order">
{{orderlist.order_id}}
</div>
</div>
</table>
You can modify it accordingly.
This will help you,
<tr ng-repeat="item in listOfData">
<td>
<ul>
<li>
{{item.order}} // or print your array element there
</li>
</ul>
</td>
I am a beginner in AngularJS.
I developped a Service with JAVA and I Consume it in angular to delete a Contact object.
In AngularJS I have this code on my home page :
<!--RESULTS-->
<form>
<table class="table table-striped" ng-controller="HomeController">
<tr>
<th></th>
<th>Nom</th>
<th>Prénom</th>
<th>Téléphone</th>
<th>Email </th>
<th></th>
</tr>
<tr ng-repeat="contact in allContacts | filter:search | orderBy:'lastName'">
<td align="center"><img src="{{contact.picture}}" height="40" width="40"/></td>
<td class="td_data">{{contact.lastName}}</td>
<td class="td_data">{{contact.firstName}}</td>
<td class="td_data">{{contact.phone_1+" "+contact.phone_2}}</td>
<td class="td_data">{{contact.email}}</td>
<td class="td_data"><button type="button" class="btn btn-danger" ng-controller="HomeController" ng-click="deleteContact(contact)"><i class="glyphicon glyphicon-trash"></i></button></td>
</tr>
</table>
In my controller I have this code :
var module = angular.module('home.controllers', [])
.run(function($rootScope) {
$rootScope.is_hide_add_message = true;
$rootScope.alert_message = "";
})
module.controller('HomeController', function ($scope, $rootScope, $state, Contacts, $timeout) {
var allContacts = {};
/** DELETE A CONTACTS*/
$scope.deleteContact = function(contact){
/** GET INDEX OF OBJECT TO DELETE */
var index = $scope.allContacts.indexOf(contact);
/** DELETE THE OBJECT SELECTED */
Contacts.deleteContact(contact.id);
/** DELETE THE OBJECT FROM THE JSON */
$scope.allContacts.splice(index, 1);
$rootScope.alert_message = "Le contact a été supprimé avec succès.";
/**DISPLAY THE MESSAGE*/
$rootScope.is_hide_add_message = false;
$timeout(function() {
$rootScope.is_hide_add_message = true;
}, 3000);
};
}
);
when I click on the delete button the object is deleted in the database but my <table> is not refreshed. When I debug the code $scope.allContacts.splice(index, 1); is working fine. but the table is not refreshed
I think the problem lays with the fact you specify ng-controller="HomeController" twice. You can delete it on the button
May be this will help i have added demo code here.
please have a look on it
var app = angular.module('myApp', []);
app.controller('HomeController', function($scope) {
var Contacts = [{
"lastName": "ABC1",
"firstName": "XYZ",
"phone_1": "123456",
"phone_2": "789456",
"email": "abcXyz#gmail.com",
}, {
"lastName": "ABC2",
"firstName": "XYZ",
"phone_1": "123456",
"phone_2": "789456",
"email": "abcXyz#gmail.com",
}, {
"lastName": "ABC3",
"firstName": "XYZ",
"phone_1": "123456",
"phone_2": "789456",
"email": "abcXyz#gmail.com",
}, {
"lastName": "ABC4",
"firstName": "XYZ",
"phone_1": "123456",
"phone_2": "789456",
"email": "abcXyz#gmail.com",
}, {
"lastName": "ABC5",
"firstName": "XYZ",
"phone_1": "123456",
"phone_2": "789456",
"email": "abcXyz#gmail.com",
}];
$scope.allContacts = Contacts;
/** DELETE A CONTACTS*/
$scope.deleteContact = function(contact) {
/** GET INDEX OF OBJECT TO DELETE */
var index = $scope.allContacts.indexOf(contact);
/** DELETE THE OBJECT FROM THE JSON */
$scope.allContacts.splice(index, 1);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<form ng-app="myApp">
<table class="table table-striped" ng-controller="HomeController">
<tr>
<th>Nom</th>
<th>Prénom</th>
<th>Téléphone</th>
<th>Email</th>
<th>Action</th>
</tr>
{{allContacts}}
<tr ng-repeat="contact in allContacts | filter:search | orderBy:'lastName'">
<td class="td_data">{{contact.lastName}}</td>
<td class="td_data">{{contact.firstName}}</td>
<td class="td_data">{{contact.phone_1+" "+contact.phone_2}}</td>
<td class="td_data">{{contact.email}}</td>
<td class="td_data">
<button type="button" class="btn btn-danger" ng-click="deleteContact(contact)">delete<i class="glyphicon glyphicon-trash"></i>
</button>
</td>
</tr>
</table>
I'm using a table in which I'm displaying some objects. I'm using jquery (bad, I know. But only thing I could get working) to add/remove class ng-hide from all elements with a specific ID. This results in a column being hidden and it works fine. But when any updates from the server comes and I use $scope.rows.push(object) and $scope.apply() the order of the columns gets messed up and the hidden column gets right back..
<!doctype html>
<html ng-app="plunker">
<head>
<script data-require="angular.js#*" data-semver="1.2.0" src="http://code.angularjs.org/1.2.0/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body>
<div ng:controller="MainCtrl">
<table>
<thead style="font-weight: bold;">
<tr>
<td class="text-right" data-col-id="Value1">Value1</td>
<td class="text-right" data-col-id="Value2">Value2</td>
<td class="text-right" data-col-id="Value3">Value3</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td class="text-right" data-col-id="Value1">{{row.Value1}}</td>
<td class="text-right" data-col-id="Value2">{{row.Value2}}</td>
<td class="text-right" data-col-id="Value3">{{row.Value3}}</td>
</tr>
</tbody>
</table>
<p>Visible Columns:</p>
<br />
<div class="cbxList" ng-repeat="column in columnsTest">
<input type="checkbox" ng-model="column.checked" ng-change="columnToggled(column)"> {{column.id}}
</div>
</div>
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.columnsTest = [{
id: 'Value1',
checked: true
}, {
id: 'Value2',
checked: true
}, {
id: 'Value3',
checked: true
}];
$scope.rows = [{
id: 1,
"Value1": 911,
"Value2": 20,
"Value3": 20
}, {
id: 2,
"Value1": 200,
"Value2": 20,
"Value3": 20
}];
$scope.columnToggled = function(column) {
$('[data-col-id="' + column.id + '"]').each(function() {
var element = this;
if ($(element).hasClass('ng-hide')) {
$(element).removeClass('ng-hide');
} else {
$(element).addClass('ng-hide');
}
});
};
//trigger update
window.setInterval(function() {
$scope.simulateUpdates($scope.rows[0]);
}, 5000);
$scope.simulateUpdates = function (row) {
var newRow =
{
id: 1,
"Value1": Math.floor(Math.random() * 100) + 1,
"Value2": Math.floor(Math.random() * 100) + 1,
"Value3": Math.floor(Math.random() * 100) + 1
}
updateRow(newRow);
$scope.$apply();
}
function updateRow(row) {
for (var i = 0; i < $scope.rows.length; i++) {
if ($scope.rows[i].id === row.id) {
$scope.rows[i] = row;
}
}
}
});
Here is a demo of my problem in a minor scale: http://plnkr.co/edit/1tGci7qX9ZFIk69uNfIf?p=preview (uncheck one of the columns)
You overcomplicate things a bit: your model seems to be pretty simple actually. The key is using templates to express it properly. That's how it might look like, for example:
<table>
<thead>
<tr>
<th class="text-right" ng-repeat="column in columnsTest"
ng-if="column.checked" ng-bind="column.id"></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="column in columnsTest"
ng-if="column.checked" ng-bind="row[column.id]"></td>
</tr>
</tbody>
</table>
<p>Visible Columns:</p>
<br />
<div class="cbxList" ng-repeat="column in columnsTest">
<input type="checkbox" ng-model="column.checked">{{column.id}}
</div>
See? No need for that extra function: when you change the specific column checked attribute, it's automatically updated in all the corresponding views.
Demo.
I have fixed your code without using jQuery.
<table>
<thead style="font-weight: bold;">
<tr>
<th ng-repeat="column in columnsTest" class="text-right" data-col-id="column.id" ng-show="column.checked">
{{column.id}}
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td class="text-right" data-col-id="Value1" ng-show="columnsTest[0].checked">{{row.Value1}}</td>
<td class="text-right" data-col-id="Value2" ng-show="columnsTest[1].checked">{{row.Value2}}</td>
<td class="text-right" data-col-id="Value3" ng-show="columnsTest[2].checked">{{row.Value3}}</td>
</tr>
</tbody>
</table>
<div class="cbxList" ng-repeat="column in columnsTest">
<input type="checkbox" ng-model="column.checked">{{column.id}}
</div>
You don't need to bind the ng-change function to the input checkbox since you already assigned it the ng-model using two-way data-binding.
The following is the working :Plunker