AngularJS Array shows all ID of field every time on same index - javascript

I have a static array and I am trying to show a particular field of this array through ng-repeat, but my array shows every time the ID field on single index.
This is what my output screenshot looks like
You can find my code below,
function monthCalendarController($scope, $http, $rootScope, $filter, $location, WebService, CalendarEventService) {
$scope.eventSelected = function(event) {
var params = {
id: event.event.id
};
var url = $rootScope.url + '/v1/show_event';
var token = window.localStorage['token'];
var result = WebService.makeServiceCallHeader(url, params, $rootScope.POST, token);
result.then(function(response) {
if (response.status == 200) {
CalendarEventService.addEvent(response.data.event);
$location.path("/calendarEvent");
} else {
WebService.showAlert('Problem in Loading');
}
}, function(response) {
console.log('' + JSON.stringify(response));
});
};
$scope.persons = [
{ "id": 1, "name": "A", "select": true },
{ "id": 2, "name": "B", "select": true },
{ "id": 3, "name": "C", "select": true },
{ "id": 4, "name": "D", "select": true },
{ "id": 5, "name": "E", "select": true },
{ "id": 6, "name": "F", "select": true },
{ "id": 0, "name": "G", "select": true }
];
console.log($scope.counts);
$scope.selectDate = function(date) {
$scope.selectedDate = date.date;
$scope.showEventsDiv = true;
};
};
HTML
<div ng-controller="monthCalendarController">
<table class="table table-bordered monthview-datetable monthview-datetable">
<thead>
<tr>
<th ng-show="showWeeks" class="calendar-week-column text-center">#
</th>
<th ng-repeat="label in labels track by $index" class="text-center">
<small>{{label}}
</small>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows track by $index">
<td ng-show="showWeeks" class="calendar-week-column text-center">
<small>
<em>{{ weekNumbers[$index] }}</em>
</small>
</td>
<td ng-repeat="dt in row track by dt.date"
class="monthview-dateCell"
ng-click="select(dt.date)"
ng-class="{\'text-center\':true, \'monthview-current\': dt.current&&!dt.selected&&!dt.hasEvent,\'monthview-secondary-with-event\': dt.secondary&&dt.hasEvent, \'monthview-primary-with-event\':!dt.secondary&&dt.hasEvent&&!dt.selected, \'monthview-selected\': dt.selected}">
<div ng-class="{\'text-muted\':dt.secondary}" ng-click="selectDate(dt.date)">
<p ng-repeat="person in persons">
{{person.id}}!
</p>
{{dt.label}}
</div>
</td>
</tr>
</tbody>
</table>
<div ng-if="showEventDetail" class="event-detail-container" ng-show="showEventsDiv">
<div class="scrollable" style="height: 200px">
<div class="col-md-12 col-xs-12" style="font-size: 18px; padding-left: 15px;">
<i class="ion-calendar">
</i>{{selectedDate.date |date:\'MM/dd/yyyy\'}}
</div>
<div style="clear: both">
</div>
<div class="item item-divider event">
Events
</div>
<table class="table table-bordered table-striped table-fixed">
<tr ng-repeat="event in selectedDate.events" ng-if="selectedDate.events">
<td ng-if="!event.allDay" class="monthview-eventdetail-timecolumn cal-date-txt">
{{event.startTime|date: \'HH:mm\'}} {{event.endTime|date: \'HH:mm\'}}
</td>
<td ng-if="event.allDay" class="monthview-eventdetail-timecolumn">
All day
</td>
<td class="event-detail cal-date-txt day" ng-click="eventSelected({event:event})">
{{event.title}}
</td>
</tr>
<tr ng-if="!selectedDate.events">
<td class="no-event-label">No Events</td>
</tr>
</table>
</div>
</div>
</div>
Array always shows ID single index.
Can someone explain and help me ? I can still not figure out why.

Related

How to repeat an array in angular js

How to ng-repeat an array in angular, I want to loop gpa in my view.
[
{
"id": 1,
"name": "Pre-Algebra",
"selected": true,
"gpa": [
{
"grade_date": null,
"grade_type": null,
"grade_percent": null,
"letter_grade": null
},
{
"grade_date": null,
"grade_type": null,
"grade_percent": null,
"letter_grade": null
}
]
},
{
"id": 2,
"name": "Pre-Calculus",
"selected": true
}
]
View Code:
<div ng-repeat="course in ctrl.subjectCourseGrades| filter: {selected : true} track by $index">
<table class="academy-table gpa-table" ng-class="!ctrl.editAcademyToggle?'data-view':''">
<tr ng-repeat="gpa in course.gpa" ng-if="!ctrl.editAcademyToggle" class="ots-data">
<td>
<b>Id is : {{$index}}<span ng-bind="gpa.grade_date"></span></b>
</td>
</tr>
</table>
</div>
Where I am doing wrong?
You don't need to use $index in the ngRepeat expression
Use
<tr ng-repeat="gpa in course.gpa"
instead of
<tr ng-repeat="gpa in course.gpa[$index]"
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
this.subjectCourseGrades = [{
"id": 1,
"name": "Pre-Algebra",
"selected": true,
"gpa": [{
"grade_date": null,
"grade_type": null,
"grade_percent": null,
"letter_grade": null
},
{
"grade_date": null,
"grade_type": null,
"grade_percent": null,
"letter_grade": null
}
]
}];
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl as ctrl">
<div ng-repeat="course in ctrl.subjectCourseGrades | filter: {selected : true} track by $index">
<table class="academy-table gpa-table">
<tr ng-repeat="gpa in course.gpa" class="ots-data">
<td>
<b>Id is : {{$index}}<span ng-bind="gpa.grade_date"></span></b>
</td>
</tr>
</table>
</div>
</div>
</body>
</html>
Remove $index from ng-repeat
<tr ng-repeat="gpa in course.gpa" ng-if="!ctrl.editAcademyToggle" class="ots-data">
<td>
<b>Id is : {{$index}}<span ng-bind="gpa.grade_date"></span></b>
</td>
</tr>
Edit1 : After looking to your question, it seems you are using controller as instead $scope. You need this:
<tr ng-repeat="gpa in ctrl.course.gpa"></tr>
Edit 2: div is not a valid table element. This may be the reason for not working. Use tbody .
<tbody ng-repeat="course in ctrl.subjectCourseGrades| filter: {selected : true} track by $index">
<tr ng-repeat="gpa in course.gpa" ng-if="!ctrl.editAcademyToggle" class="ots-data">
<td>
<b>Id is : {{$index}}<span ng-bind="gpa.grade_date"></span></b>
</td>
</tr>

On click of checkAll checkbox, push its objects in another array object and remove from existing array

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

Refresh a JSON after deleting an object in AngularJS

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>

AngularJS: Prevent item already in array from being added again

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/

AngularJS <select> two way data binding for <option> coming from AJAX call

I have this Controller:
JApp.controller('WebsiteController', function($scope, $resource) {
var UsersService = $resource('/auth/users', {});
$scope.adding = false;
$scope.users = [];
$scope.addUser = function() {
$scope.adding = true;
UsersService.query({}, function(data) {
$scope.users = data;
$scope.selectedUser = data[0];
});
}
$scope.cancelAddUser = function() {
$scope.adding = false;
}
});
My HTML:
<section class="vbox" ng-controller="WebsiteController">
<section class="panel animated fadeInDown">
<header class="panel-heading">
<h3>{{selectedUser.last_name}} </h3> <!-- Just to test I print it here -->
</header>
<div class="panel-body m-b">
<div class="row text-sm wrapper">
#if (role_admin())
<i class="icon-plus"></i> New Website
#endif
</div>
<div class="table-responsive">
<table class="table table-striped b-t text-sm">
<thead>
<tr>
<th>URL</th>
<th>Assigned to</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<!-- Outside this <tr> doesn't work -->
<tr ng-repeat="website in websites">
<td> {{website.url}}</td>
<td>
<span ng-repeat="assigned in website.users"> <span class="label label-info"> {{assigned.first_name}} </span> </span>
<a ng-click="addUser()" ng-hide="adding" class="btn btn-success btn-xs"> Add new </a></span>
<select ng-hide="!adding"
name="myselect"
ng-model="selectedUser"
ng-options="u.first_name for u in users">
</select>
Cancel
<input type="text" ng-model="selectedUser.first_name"> <!-- It works here! -->
</td>
<td>
<i class="icon-pencil"></i> Edit
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</section>
Updated: Notice that it works in my <input> next to the <select>, but doesn't work in my <header> (only binds once)
So when I click on the add user, the AJAX call will retrieve list of users, and successfully show it in the <select> and by default, selectedUser will be pointing at data[0] which is the first user. But now the two way binding is now bound to data[0] instead. If I change my selection to other user, selectedUser is not updated. But if I update my selectedUser, let's say the name, the name in the dropdown list also change.
I have tried not using the line
$scope.selectedUser = data[0];
but still doesn't work anyway, it is not bound at all though I specify ng-model="selectedUser".
The JSON returned:
[
{
"id": 1,
"role_id": 1,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "admin#admin.com",
"username": "admin",
"first_name": "Admin",
"last_name": "Istrator"
},
{
"id": 2,
"role_id": 2,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "johndoe#gmail.com",
"username": "john",
"first_name": "John",
"last_name": "Doe"
}
]
Anyone can help me with this? I am trying not to go down the $digest or $apply road if I don't have to.
UPDATE 2
The source of the problem is if I try to print out selectedUser outside of the following ng-repeat in my above HTML:
<tr ng-repeat="website in websites"> ...... </tr>
Fiddle to illustrate my problem: http://jsfiddle.net/jofrysutanto/4nfyV/3/
Try This
HTML:
<div ng-app="myApp">
<section class="vbox" ng-controller="WebsiteController">
<section class="panel animated fadeInDown">
<header class="panel-heading">
<h3>{{mySelectedUser.last_name}} </small> <!-- Just to test I print it here -->
</header>
<div class="panel-body m-b">
<div class="table-responsive">
<table class="table table-striped b-t text-sm">
<thead>
<tr>
<th>URL</th>
<th>Assigned to</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="website in websites">
<td>
<span ng-repeat="assigned in website.users"> <span class="label label-info"> {{assigned.first_name}} </span> </span>
<a ng-click="addUser()" ng-hide="adding" class="btn btn-success btn-xs"> Add new </a></span>
<select ng-hide="!adding"
name="myselect"
ng-model="selectedUser"
ng-change="abc(selectedUser)"
ng-options="u.first_name for u in users">
</select>
Cancel
<input type="text" ng-model="selectedUser.first_name"> <!-- It works here! -->
</td>
<td>
<i class="icon-pencil"></i> Edit
</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</section>
</div>
Controller :
var JApp = angular.module('myApp', []);
JApp.controller('WebsiteController', function($scope) {
//var UsersService = $resource('/auth/users', {});
$scope.adding = false;
$scope.users = [];
$scope.websites = [
{
"id": 1,
"url": "www.google.com",
"cms": "Wordpress"
}
];
$scope.addUser = function() {
$scope.adding = true;
var data = [
{
"id": 1,
"role_id": 1,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "admin#admin.com",
"username": "admin",
"first_name": "Admin",
"last_name": "Istrator"
},
{
"id": 2,
"role_id": 2,
"created_at": "2013-09-19 05:54:36",
"updated_at": "2013-09-19 05:54:36",
"email": "johndoe#gmail.com",
"username": "john",
"first_name": "John",
"last_name": "Doe"
}
];
// UsersService.query({}, function(data) {
$scope.users = data; // suppose data is coming from UsersService.query
$scope.selectedUser = data[1];
$scope.mySelectedUser = $scope.selectedUser ;
// });
}
$scope.abc = function(a) {
$scope.mySelectedUser = a;
}
$scope.cancelAddUser = function() {
$scope.adding = false;
}
});
See DEMO
The value of the select dropdown options is u.first_name, so either do this:
$scope.selectedUser = data[0].first_name;
Or change it to use ids or something like this.
ng-options="u.id as u.first_name for u in users"
$scope.selectedUser = data[0].id;

Categories