How to properly iterate over an array elements with Angular JS? - javascript

I want to render a table adding row per each objects in an array.
I got a Controller like:
app.controller('SignUpController',function ($scope, $http) {
var that = this
that.users = []
that.queryUsers = function() {
console.log("I'm being triggered")
$http.get("/existingUsers").
success(function (data,status,headers,config) {
console.log(data)
that.users = data
console.log(that.users)
}).
error(function (data,status, headers, config) {
console.log(status)
})
}
})
And the table markup:
<table class="table table-bordered">
<th ng-repeat="th in ['mail','Administrador','Miembro desde']">{{th}}</th>
<tr ng-repeat="p in signup.users">
<td>{{p._id}}</td>
<td>{{p.mail}}</td>
<td>{{p.admin}}</td>
</tr>
</table>
Ttable is within a div with ng-controller="SignUpController as signup". When I click a button I trigger queryUsers actually seein results in browser console:
[Object, Object, Object, Object, Object, Object, Object, Object, Object, Object]
Both mail and _id are existing attributes per each object.
So the AJAX is being done and the array I should be iterating and rendering to HTML rows actually exists and is populated, but no rows are shown.
Why?
Edit
I tried not modifying the scope:
app.controller('SignUpController', function ($scope,$http) {
$scope.users = []
$scope.queryUsers = function() {
console.log("I'm being triggered")
$http.get("/existingUsers").
success(function (data,status,headers,config) {
console.log(data)
$scope.users = data
console.log($scope.users)
}).
error(function (data,status, headers, config) {
console.log(status)
})
}
})
<div class="tab-pane" id="usecase11" ng-controller="SignUpController">
<h3>Colaboradores</h3>
<div class="row">
<div class="col-sm-6">
<table class="table table-bordered">
<th ng-repeat="th in ['mail','Administrador','Miembro desde']">{{th}}</th>
<tr ng-repeat="p in users">
<td>{{p._id}}</td>
<td>{{p.mail}}</td>
<td>{{p.admin}}</td>
<td style="border:none;"><a class="close" ng-click="">$</a></td>
<td style="border:none;"><a class="close" ng-click="">*</a></td>
</tr>
</table>
</div>
</div>
</div>
However, again I can see such array printed at browser console but nothing rendered to HTML
Here is the evidence that queryUsers is being called and that $scope.users is getting something after it.
Something interesting is that I got: {{users}} right after the table and it's displaying an empty array.
Just in case this is the GET handling server code:
app.get('/existingUsers',function (request, response) {
membersCollection.find({},{"password":0}, function (err, data) {
if (err) response.send(404)
else {
data.toArray(function (err, docs) {
if (err) {
console.log(error)
response.send("Error")
}
response.send(JSON.stringify(docs, null, 4))
})
}
})
}

You don't modify the $scope. Here is the corrected code:
app.controller('SignUpController',function ($scope, $http) {
$scope.users = []
$scope.queryUsers = function() {
console.log("I'm being triggered")
$http.get("/existingUsers").
success(function (data,status,headers,config) {
console.log(data)
$scope.users = data
console.log($scope.users)
}).
error(function (data,status, headers, config) {
console.log(status)
})
}
})
HTML:
<table class="table table-bordered">
<th ng-repeat="th in ['mail','Administrador','Miembro desde']">{{th}}</th>
<tr ng-repeat="p in users">
<td>{{p._id}}</td>
<td>{{p.mail}}</td>
<td>{{p.admin}}</td>
</tr>
</table>

Related

How to get object of array in view file in ionic framework

I am working with ionic framework I am getting data into localStorage.
.controller('AppCtrl', function(Auth,$scope,$http, $ionicModal,$location,$state,$window,$localStorage, $sessionStorage,$timeout,$ionicSideMenuDelegate) {
//$scope.$on('$ionicView.leave', function () { $ionicSideMenuDelegate.canDragContent(true) });
$scope.adminData = $localStorage.adminData;
$scope.forgetData = $sessionStorage.forgetData;
$scope.levels = $localStorage.levels;
$scope.loginData = {}
// Create the login modal that we will use later
$ionicModal.fromTemplateUrl('templates/login.html', {
scope: $scope
}).then(function(modal) {
$scope.modal = modal;
});
$scope.levels = function() {
$http({
url: 'http://localhost/bearscoaching/api/classes',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8'}
})
.then(function successCallback(response)
{
function isObjectHasData(object)
{
return (object != null && typeof object != 'undefined' && Object.keys(object).length > 0);
}
if(isObjectHasData(response.data))
{
$scope.dp = response.data;
$localStorage.levels = $scope.dp;
/*angular.forEach($localStorage.levels, function(user, arrayID)
{
alert(user.name);
});*/
$state.go('app.search');
}
else
{
alert("Data is not available");
//$state.go('app.dashboard');
}
}, function errorCallback(response)
{
console.log(response);
// $state.go('app.dashboard');
alert("Data is not available");
});
};
})
when I run foreach loop I am getting every name in alert.But when I get these data in view file like:
<ion-modal-view>
<ion-view view-title="Marie Simpson" id="mainpage" hide-nav-bar="false">
<ion-content padding="true" scroll="false">
<table>
<thead>
<th>Name</th>
</thead>
<tbody ng-repeat="item in levels">
<tr>
<td>{{item.name}}</td>
</tr>
</tbody>
</table>
</ion-content>
</ion-view>
</ion-modal-view>
I am not getting name of list.my response is
ngStorage-levels: "[{"id":2,"name":"Level I"},{"id":3,"name":"Level I…":6,"name":"Level V"},{"id":7,"name":"Level VI"}]"

Angular Table Refresh

I have an api that gets called on page load. The data from the api is loaded into a table via angular ng-repeat. I also have a javascript function that gets called every 10 seconds that calls the same api for the same dataset. I Would like to know how i can apply the new dataset to the table and replace the old if the dataset changes and how to visually show this change with animation. The code is below.
Table code
<body ng-app="myApp" ng-controller="ScansController">
<div class="bs-example" id="scan-table">
<table id="scansTable" class="table table-striped">
<thead>
<tr>
<th>ScanId</th>
<th>First Name</th>
<th>Last Name</th>
<th>Time Stamp</th>
</tr>
<tr ng-repeat="scan in Scans">
<td>
{{scan.scanId}}
</td>
<td>
{{scan.firstName}}
</td>
<td>
{{scan.lastName}}
</td>
<td>
{{scan.timeStamp}}
</td>
</tr>
</thead>
</table>
</div>
Javascipt interval code
<script>
window.setInterval(function () {
$.ajax({
url: 'api/scans/',
type: 'Get',
dataType: 'json',
success: function (data) {
//Something here
},
error: function () {
alert("something failed");
}
});
}, 10000);
</script>
Angular Code
var myApp = angular.module('myApp', []);
myApp.service('dataService', function ($http) {
this.getData = function () {
return $http({
method: 'GET',
url: '/api/scans/'
});
}
});
myApp.controller('ScansController', function ($scope, dataService) {
$scope.Scans = [];
dataService.getData().then(function (result) {
$scope.Scans = result.data;
console.log(result.data);
});
});
You need to stay inside the current scope.
Setting an interval on a $http call is poison. Use a $timeout inside the success callback to recursively call the next interval.
myApp.controller('ScansController', function ($scope, $timeout, dataService) {
$scope.Scans = [];
function fetchData(){
dataService.getData().then(function (result) {
$scope.Scans = result.data;
$timeout(function(){ fetchData(); },10000);
});
}
fetchData();
});
As far as the table refresh that didnt get addressed, this is how i was able to make it work. I downloaded and applied the animate.css. I then gave the table a starting class to animate it on class load. I then have a function that fetches the array of data on page load and then another that fetches every .5 seconds and compares. If anything has changed, then the class is reapplied and it shows animation.
Angular Ng-Repeat Table
<link href="~/Content/animate.min.css" rel="stylesheet" />
<h1>
Scans
</h1>
<body ng-app="myApp" ng-controller="ScansController" >
<table id="scansTable" class="table table-striped">
<thead>
<tr>
<th>ScanId</th>
<th>First Name</th>
<th>Last Name</th>
<th>Time Stamp</th>
</tr>
<tr ng-repeat="scan in Scans" ng-class-odd="'odd'" ng-class-even="'even'" class="animated bounceIn">
<td>
{{scan.scanId}}
</td>
<td>
{{scan.firstName}}
</td>
<td>
{{scan.lastName}}
</td>
<td>
{{scan.timeStamp}}
</td>
</tr>
</thead>
</table>
Angular Controller
var myApp = angular.module('myApp', []);
myApp.service('dataService', function ($http) {
this.getData = function () {
return $http({
method: 'GET',
url: '/api/scans/'
});
}
});
myApp.controller('ScansController', function ($scope, dataService, $timeout) {
$scope.Scans = [];
$scope.NewScans = [];
function fetchData() {
dataService.getData().then(function (result) {
$scope.Scans = result.data;
$("#scansTable").removeClass('animated bounceIn');
});
}
function fetchNewData() {
dataService.getData().then(function (result) {
$scope.NewScans = result.data;
if ($scope.Scans.length != $scope.NewScans.length)
{
$("#scansTable").addClass('animated bounceIn');
$scope.Scans = $scope.NewScans
}
$timeout(function () { fetchNewData(); }, 500);
});
}
fetchData();
fetchNewData();
});

How can I pass my viewmodel data from my view to my controller?

Currently, my view looks something like:
#using (Html.BeginForm("CreateUser", "Home", FormMethod.Post))
{<form ng-controller="MyController">
<table cellpadding="2" cellspacing="2">
<tr>
<td>#Html.LabelFor(model => model.FirstName) </td>
<td>#Html.TextBoxFor(model => model.FirstName, new { ng_model = "user.firstName" }) </td>
</tr>
<tr>
<td>#Html.LabelFor(model => model.LastName) </td>
<td>#Html.TextBoxFor(model => model.LastName, new { ng_model = "user.lastName" })) </td>
</tr>
<tr>
<td> </td>
<td><input type="submit" value="Save" ng-click="addUser()" /></td>
</tr>
</table>
</form>
}
My Controller (on ASP.NET MVC side):
[HttpPost]
public ActionResult Create(UsersViM usersVM)
{
//Sets the model equal to viewmodel
//Saves the name in session and redirects to previous view with new list of names.
}
I am wondering, what data should I be passing from my view to my controller? That is, how do I pass my model from my view to my controller? How do I set that up in angular?
$scope.addUser = function() {
var data = {
//user.firstname, user.lastname but how does angular know what user is?
//User is defined as the Model on the ASP.NET MVC side.
};
$http
.post('Home/Create', data)
.success(function(data, status, headers, config) {
})
.errors(function(data, status, headers, config) {
});
};
$scope.addUser = function () {
$http
.post('Home/CreateUser', usersViewModel)
.success(function (data, status, headers, config) {
successFn();
})
.errors(function (data, status, headers, config) {
errorFn();
});
};
Your back-end model fields should be same as like front-end model fields so that the mapping will not generate an error.
Suppose if you have defined you scope as mentioned below then define the user property so that angular can bind it with ng-model properties.
function MyController($scope) {
$scope.user= {};
$scope.addUser= function() {
console.log(this.user);
......
};
}
When the above form is submitted $scope.addUser will contain an object of your form which can then be passed in your http post request. e.g:
Object {firstName: "Test First Name", lastName: "Test Last Name"}

Only the last directive on an AngularJS page maintains it's binding

I've got a couple directives that I intend to be reusable elements, so I'm using scope isolation. Each directive has it's own dedicated controller which pulls it's data from mongo based on url.
The problem is that only the last directive on the page is showing the data to which it is bound. Doesn't matter what order I put the directives in, only the last one works, and each one does work. For ex I do get the customer dump into the log, but nothing shows up in {{ here }} unless it's the last directive in the page.
I'm fairly certain this is a scope issue, but these are meant to be isolated for reuse, so why would they be blanking each other out?
On the code...
js
.controller('getCustomerList',function(customerIOService){
_this = this;
_this.customers = {};
customerIOService.list()
.success(function(data, status, headers, config){
_this.customers = data;
})
.error(function(data, status, headers, config){
console.log('error Data :: ');
//console.log(data);
if(status == 403){
_this.error = 'You need to be logged in to view this page.';
}else{
_this.error = 'An error occured during the customer list request.';
}
});
})
.controller('getCustomerAppointments',function(customerIOService){
_this = this;
_this.appointments = {};
customerIOService.getAppointments()
.success(function(data, status, headers, config){
_this.appointments = data;
//console.log(data);
})
.error(function(data, status, headers, config){
console.log('error Data :: ');
//console.log(data);
if(status == 403){
_this.error = 'You need to be logged in to view this page.';
}else{
_this.error = 'An error occured during the appointments list request.';
}
});
})
.controller('getCustomerSingle', function(customerIOService) {
_this = this;
_this.customer = {};
_this.updateSuccess = false;
customerIOService.one()
.success(function(data, status, headers, config){
_this.customer = data;
console.log(data);
})
.error(function(data, status, headers, config){
console.log('error Data :: ');
//console.log(data);
if(status == 403){
_this.error = 'You need to be logged in to view this page.';
}else{
_this.error = 'An error occured during the customer fetch request.';
}
});
_this.update = function(){
customerIOService.update(_this.customer)
.success(function(data, status, headers, config){
_this.customer = data;
_this.updateSuccess = true;
})
.error(function(data, status, headers, config){
console.log('error Data :: ');
//console.log(data);
if(status == 403){
_this.error = 'You need to be logged in to view this page.';
}else{
_this.error = 'An error occured during the customer update.';
}
});
}
})
.directive('customerList',function() {
return {
scope: {},
restrict:'E',
templateUrl: 'views/templates/customersList.html',
replace: true,
controller: 'getCustomerList',
controllerAs: 'ctrl'
};
})
.directive('customerSingle',function() {
return {
scope: {},
restrict:'E',
templateUrl: 'views/templates/customersSingle.html',
replace: true,
controller: 'getCustomerSingle',
controllerAs: 'singleCustCtrl'
};
})
.directive('customerAppointments',function() {
return {
scope: {},
restrict:'E',
templateUrl: 'views/templates/customersAppointmentsList.html',
replace: true,
controller: 'getCustomerAppointments',
controllerAs: 'custApptCtrl'
};
})
Parent html
<section>
<div class="sectionHeader oswald font-light panel panel-default panel-body panel-success text-center">Customer Update</div>
<div class="panel panel-default panel-body panel-success">
<customer-single></customer-single>
</div>
<div class="panel panel-default panel-body panel-success">
<customer-appointments><customer-appointments/>
</div>
<div class="panel panel-default panel-body panel-success">
<customer-list><customer-list/>
</div>
</section>
Directive html
<span>
<a href="/appointments/create/{{custApptCtrl.customer._id}}">
<span class="fa-stack fa-lg pull-left">
<i class="fa fa-plus fa-stack-1x "></i>
</span>
Add Appointment
</a>
<table class="table table-striped">
<thead>
<tr>
<th>Caregiver</th>
<th>Start</th>
<th>End</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="appt in custApptCtrl.appointments">
<td>{{ appt.employee.lastName }}, {{ appt.employee.firstName }}</td>
<td>{{ appt.startDate }}</td>
<td>{{ appt.endDate }}</td>
<td><span class="glyphicon glyphicon-pencil"></span></td>
</tr>
</a>
</tbody>
</table>
</span>
Your controllerAs syntax seems a little fishy to me, can you give this a try instead:
controller:
app.controller('xyz', function() {
var xyzVm = this;
// and now use this xyzVm instead of _this everywhere in the controller
});
and then in your directive
.directive('customerList',function() {
return {
scope: {},
restrict:'E',
templateUrl: 'views/templates/customersList.html',
replace: true,
controller: 'xyz',
controllerAs: 'xyzVm'
};
})
so now your template can use xyzVm.appointments within the repeater

How to process an array with AngularJS?

I have an API returning the following simple JSON array:
[
"efd98ad-first_key",
"100eb0a-second_key"
]
I am trying to render this as a table with Angular:
<div name="listkeys" class="container">
<div class="starter-template">
<div ng-bind-html="message"></div>
<table class="table table-striped table-bordered table-condensed sortable" ng-init="getKeys()">
<tr>
<th>bucket</th>
</tr>
<tr ng-repeat="bucket in buckets">
<td>{{bucket}}</td>
</tr>
</table>
</div>
</div>
JS:
var app = angular.module('flipDaSwitch', ['ngSanitize']);
app.controller('ListKeys', function($scope, $http) {
$scope.getKeys = function() {
$http.get('/api/keys').
success(function (data) {
$scope.response = data;
}).
error(function (data){
$scope.response = {}
});
};
});
It does not do anything but throwing an "Uncaught object" error and that is it.
How could I debug why it is failing?
You are storing the values in $scope.response, but you are using $scope.bucket at the ng-repeat:
$scope.getKeys = function() {
$http.get('/api/keys').
success(function (data) {
$scope.buckets= data;
}).
error(function (data){
$scope.buckets= {}
});
};
It looks like you do not have a scope item called buckets. I'd expect to see:
$scope.buckets = data
Inside the success callback.

Categories