List objects doesn't show using ng-repeat - html

I am not sure what i am doing wrong but my objects doesn't want to display in my partial view with angular's ng-repeat
SCRIPT
$scope.ExecutivePayList = [];
$scope.LoadExecutivesPay = function () {
$.get(loadExecutivesPayUrl, function (data) {
if (data.IsSuccess) {
//Load data
$scope.ExecutivePayList.length = 0;
//$scope.ExecutivePayList = angular.fromJson(data.Results);
for (var i = 0; i < data.Results.length; i++) {
$scope.ExecutivePayList.push(data.Results[i])
}
console.log($scope.ExecutivePayList);
}
});
};
HTML
<tr ng-repeat="executive in ExecutivePayList">
<td class="">
{{executive.NameOfIncumbent}}
</td>
<td class="">
{{executive.Position}}
</td>
<td class="">
{{executive.PatersonGrade}}
</td>
<td class="text-center">
{{executive.NumMonthsInPosition}}
</td>
<td class="text-center">
</td>
</tr>
JSON Output
{SectionID: "00000000-0000-0000-0000-000000000000", Results: Array(2), Message: null, IsSuccess: true, DetailedMessage: null}
Results: Array(2)
0:{SectionID: "b8e6466e-44b8-4a47-bdc6-a84e07200780", NameOfIncumbent: "Daily M", Position: "CEO", PatersonGrade: "", NumMonthsInPosition: 12}
1:{SectionID: "2290a579-7f86-437f-a806-36049eeb7c8b", NameOfIncumbent: "Field RH", Position: "CEO", PatersonGrade: "", NumMonthsInPosition: 12}
Not sure if this might be useful but i call my method on ng-init
<div ng-controller="ExecutivePayController" ng-init="LoadExecutivesPay()">

Firstly since you don't use angular's way to make the AJAX call you need to call angular.fromJson(data.Results). Furthermore since this is an asynchronous operation you have to manually trigger a digest cycle. So you have to call $scope.$apply() right after you update your $scope.ExecutivePayList.
Final code:
$scope.ExecutivePayList = [];
$scope.LoadExecutivesPay = function () {
$.get(loadExecutivesPayUrl, function (data) {
if (data.IsSuccess) {
//Load data
$scope.ExecutivePayList.length = 0;
$scope.ExecutivePayList = angular.fromJson(data.Results);
for (var i = 0; i < data.Results.length; i++) {
$scope.ExecutivePayList.push(data.Results[i])
}
console.log($scope.ExecutivePayList);
$scope.$apply(); // Here you trigger the digest cycle.
}
});
};
Update on how to do this in angular way.
It is recommended to have your http calls in a service instead of performing them in your controller as you do now. In any case you have to have the $http injected in your service or controller (current case).
Then your controller function should look like this:
$scope.LoadExectivesPayUrl = function() {
$http.get(loadExecutivesPayUrl).then((data) => {
if(data.IsSuccess) {
//Load data
$scope.ExecutivePayList.length = 0;
//No need to parse json because angular has done this automatically
//for you
for (var i = 0; i < data.Results.length; i++) {
$scope.ExecutivePayList.push(data.Results[i])
}
console.log($scope.ExecutivePayList);
// No need to $scope.$apply() , since digest cycle is performed
// within $http operation
}
})
}

First of all you are checking for if (data.IsSuccess) { and your output does not have it.
Secondly you are using the data.Results.length;. Also here Results is not there.

Related

Using redux-saga with setInterval - how and when to yield

Having just moved from thunks to sagas I'm trying to find the best way to call setTimeout and then from within that function call another function (in this case corewar.step()). This was my original code which works as I'd expect.
runner = window.setInterval(() => {
for(let i = 0; i < processRate; i++) {
corewar.step()
}
operations += processRate;
}, 1000/60)
This code is inside a saga and I believe that I should be able to wrap function calls within call as I've done in other areas in the application.
I've tried wrapping the setInterval call in a call and leaving everything else as it is, which results in step() never being called.
runner = yield call(window.setInterval, () => {
for(let i = 0; i < processRate; i++) {
corewar.step()
}
operations += processRate;
}, 1000/60)
I've tried, leaving the setInterval as it is and wrapping the step() function in a call and changing the anonymous function signature to function* which also results in step() never being called.
runner = window.setInterval(function*() {
for(let i = 0; i < processRate; i++) {
yield call([corewar, corewar.step])
}
operations += processRate;
}, 1000/60)
Finally, I've tried wrapping both, which again results in step() never being called.
runner = yield call(window.setInterval, function*() {
for(let i = 0; i < processRate; i++) {
yield call([corewar, corewar.step])
}
operations += processRate;
}, 1000/60)
It feels like I'm missing something here so my question is, should I need to wrap these functions up in call at all or is this wrong?
The follow on question if I am supposed to wrap the outer setInterval in a call would be how should I be defining a function as a parameter to call which also wants to yield either a put or call itself?
There is a section in the saga-redux docs called "Using the eventChannel factory to connect to external events", that suggests using channels.
This section is also providing an example for a setInterval implementation:
import { eventChannel, END } from 'redux-saga'
function countdown(secs) {
return eventChannel(emitter => {
const iv = setInterval(() => {
secs -= 1
if (secs > 0) {
emitter(secs)
} else {
// this causes the channel to close
emitter(END)
}
}, 1000);
// The subscriber must return an unsubscribe function
return () => {
clearInterval(iv)
}
}
)
}
You would then use yield call and yield takeEvery to set it up:
const channel = yield call(countdown, 10);
yield takeEvery(channel, function* (secs) {
// Do your magic..
});
const anotherSaga = function * () {
const runner = yield call(setInterval, () => {
console.log('yes');
}, 1000);
console.log(runner);
}
This works pretty fine for me. In your second snippet there is a double ) at the end where should be only one.
A little late to the party here but this is the top search result for the question of setting a timer in a saga. There's an alternate solution due to the nature of sagas. From here.
I adapted this so:
function* callSelfOnTimer({ value }) {
// Do your work here
...
// If still true call yourself in 2 seconds
if (value) {
yield delay(2000);
yield call(callSelfOnTimer, { value });
}
}
For this to work you also need to add this:
const delay = (ms) => new Promise(res => setTimeout(res, ms))
function* callSelfOnTimer({ value }) {
// Do your work here
...
// If still true call yourself in 2 seconds
if (value) {
yield delay(2000);
yield call(callSelfOnTimer, { value });
}
}

Display ID in table as another Name/phrase

I am wondering if there is a way to display for example an id in a table cell as another name from another object as their id's correspond to each other.
What i want to do is to display it in a way like this if there is something similar?
<td class="tableRowText"><p>{{l.SenderId}}</p></td>
in a way like this.
ng-options="x.ProcessId as x.Name for x in PL"
so that would be something like:
<td class="tableRowText"><p>{{l.SenderId}} as x.Name for x in PL</p></td>
WISHFULLY! :P hope you guys understand i'm just trying to get my point through.
Thanks in advance!
_____________EDIT:_______________________________
So this is the Table and how i request the data.
app.factory('getTableGridDataService', function ($resource, config) {
return $resource(config.apiURL + '/Logs/GetLogEvents', {}, { 'post': { method: 'POST' } })
});
scope.loggItems = [];
$scope.fillRealTable = function () {
var arrayBody = {
Sending: $scope.paramSending,
Receiving: $scope.paramReceiving,
Logging: $scope.paramLogging,
};
var query = postTableGridDataService.post({}, arrayBody);
query.$promise.then(function (data) {
var loggItemList = data;
$scope.loggItems = loggItemList
})
}
<table class="table table-striped table-condensed table-hover" id="MainTable">
<thead>
<tr>
<th ng-click="sort('SenderId')" style="cursor:pointer;">
Sender
<span class="glyphicon glyphicon-sort" ng-show="sortKey=='SenderId'" ng-class="{'glyphicon glyphicon-menu-up':reverse, 'glyphicon glyphicon-menu-down':!reverse}"></span>
</th>
<th ng-click="sort('ReceiverId')" style="cursor:pointer;">
Reciever
<span class="glyphicon glyphicon-sort" ng-show="sortKey=='ReceiverId'" ng-class="{'glyphicon glyphicon-menu-up':reverse, 'glyphicon glyphicon-menu-down':!reverse}"></span>
</th>
<th ng-click="sort('LoggingId')" style="cursor:pointer;">
Logging source
<span class="glyphicon glyphicon-sort" ng-show="sortKey=='LoggingId'" ng-class="{'glyphicon glyphicon-menu-up':reverse, 'glyphicon glyphicon-menu-down':!reverse}"></span>
</th>
</tr>
</thead>
<tbody>
<tr dir-paginate="l in loggItems.LogEventList|filter:search|orderBy:sortKey:reverse|itemsPerPage:15" pagination-id="mainPagination">
<td class="tableRowText"><p>{{l.SenderId}}</p></td>
<td class="tableRowText"><p>{{l.ReceiverId}}</p></td>
<td class="tableRowText"><p>{{l.LoggingId}}</p></td>
</tr>
</tbody>
</table>
I also get another object from my api in which i have the names for the Sending-ID, Reciever-ID and Logging-ID and i want those names displayed in the table instead of the id's from my Object in wich i display in the tabl. how do i achieve that?
The other object with the corresponding ID's and names:
app.factory('getSearchFormData', function ($resource, config) {
return $resource(config.apiURL + '/SearchFormObj/getSearchFormItems', {} ,{'get': {method:'GET'}})
});
$scope.SL = [];
function SearchData() {
var query = getSearchFormData.get();
query.$promise.then(function (data) {
$scope.SL = data.SystemList;
console.log($scope.SL);
});
};
SearchData()
Here is the object returned from getSearchFormData:
The basic idea is in your controller which depends on both services, you wait for both promises to resolve, then loop through your log items and either replace the ids with the names, or add then names to each log item, if you want to keep the ids.
$scope.fillRealTable = function () {
var arrayBody = {
Sending: $scope.paramSending,
Receiving: $scope.paramReceiving,
Logging: $scope.paramLogging,
};
var p1 = postTableGridDataService.post({}, arrayBody).$promise;
var p2 = getSearchFormData.get().$promise;
//it might be $q.all([p1.promise,p2.promise])
$q.all([p1,p2]).then(function(data1, data2) {
var loggItemList = data1;
var SL = data2.SystemList;
loggItemList.forEach(function (item) {
item.SenderName = SL[item.SenderId].name;
item.ReceiverName = SL[item.ReceiverId].name;
item.LogginName = SL[item.LogginId].name;
});
$scope.loggItems = loggItemList;
});
}
The code in the forEach is all speculation, since you do not provide the structure of the data returned by getSearchFormData, so this example assumes it's key-value list of objects with the key being one of the ID. E.g:
{
"A001" : { name: "John Smith" },
"B001" : { name: "Bruce Wayne" }
}
P.S: An alternative to this method is to move the whole mapping in getTableGridDataService and have that service call the other, meaning your view logic remains simple, since it will receive the full result from the service.

angular ngTableParams from json

Having problem with creating table from json data.
Using Django + AngularJS
Data is not displayed.
tables.js
app.controller('tableCtrl', function(ngTableParams, tableData) {
var data = tableData
this.tableLatestContests = new ngTableParams({
page: 1,
count: 5,
}, {
total: data.length,
getData: function($defer, params) {
$defer.resolve(data.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
}
});
services.js
app.service('tableData', [$resource, function($resource) {
this.data = $resouce('data/table.json', {}, {
query: {
method: 'GET',
isArray: true,
}
}
});
data/table.json
[
{"id": 1, "market": "name", "uid": "uid"},
{"id": 2, "market": "name2", "uid": "uid2"},
]
table.html (on app changed {{ & }} to // & // because of django syntax)
<div class="card-body card-padding" data-ng-controller="tableCtrl as tctrl">
<table ng-table="tctrl.tableLastestContests" class="table table-striped table-vmiddle">
<tr ng-repeat="w in $data">
<td data-title="'ID'"> // w.id // </td>
<td data-title="'MARKET'"> // w.market // </td>
<td data-title="'UID'"> // w.uid // </td>
</tr>
</table>
</div>
Any ideas how to read and display table with tada from json ?
You are misunderstanding something. $resource creates instance of service instead of getting data from the service. This is why you have service which is capable of getting data form json instead of data form json.
this.srv = $resouce('data/table.json', {}, {
query: {
method: 'GET',
isArray: true,
}
}
this.data = this.srv.query();
After successful loading you will get data in this.data.
Of course you can change last line to something like this:
var _self = this;
this.srv.query(function(response) {
_self.data = response;
});
In case you do not want to create service, you can do:
$http.get('data/table.json').then(function(response) {
_self.data = response.data;
});
My post does not include support for errors.
You can read more here:
https://docs.angularjs.org/api/ngResource/service/$resource
https://docs.angularjs.org/api/ng/service/$http
Also, you have error in view. Use data instead of $data in ng-repeat.

How to display the returned ajax Json results in HTML (using typescript)

The client (typescript) gets different results from the server, all are in json format. Sometimes a simple json result, sometimes complex nested jsons.
I need to present the results in a (very) simple html table.
function run(): void {
var url = this.selectedKnockoutDropList();
$.ajax(url, "GET").done(data => {
console.log(data);
*** here I want to do something like :
- open/embedd results.html
- fill a table with the json results parsed somehow
});
I tried $('#...).html(data) with no success.
You need to transform the JSON into meaningful HTML. This can be done in typescript, javascript. It can be done with jQuery it can be done using javascript templates such a handlebars. It can be done with SPA frameworks like Angular.
Please post an a sample of the returned JSON and I can update with a TypeScript example not using any toolsets or libs.
JSON is an object. To output it to the document you need to first convert it to a string:
$.ajax(url, "GET").done(data => {
$('#...).html(JSON.stringify(data));
}
However, if you know what kind of data you are getting back and want to output just parts of it, you'll need to loop the JSON. For example, if you had a JSON object like:
[
{name: "Joe", age: 32},
{name: "Suzy", age 23},
{name: "Tom", age 28}
]
You could output the names like this:
$.ajax(url, "GET").done(data => {
data.forEach(function(person) {
$(ul).append('<li>' + person.name + '</li>');
});
}
Martin and Robert - thanks for the quick replies. I took your advises and came with the following generic solution (which can display html text returned from the server or nested json object in a table) :
HTML:
<!--HTML-->
<div data-bind="visible: isHtml, html: htmlView"></div>
<!--SIMPLE JSON-->
<div data-bind="visible: isJson">
<table>
<thead>
<tr data-bind="foreach: columns">
<th data-bind="text: $data"></th>
</tr>
</thead>
<tbody data-bind="foreach: rows">
<tr data-bind="foreach: $parent.columns">
<td data-bind="text: $parent[$data]"></td>
</tr>
</tbody>
</table>
</div>
TS:
function run(): void {
this.isHtml(false);
this.isJson(false);
$.ajax(url, "GET").done(data => {
var jsonObj = data;
if (typeof (data) === "string") {
this.htmlView(data);
this.isHtml(true);
return;
}
if (data instanceof Array === false) {
jsonObj = [data];
}
this.columns([]);
this.rows([]);
for (var i = 0; i < jsonObj.length; i++) {
var item = jsonObj[i];
var newItem = {};
for (var key in item) {
if (i === 0)
this.columns.push(key);
if (typeof item[key] !== "object") {
newItem[key] = item[key];
} else {
for (var deeperKey in item[key]) {
this.columns.push(deeperKey);
newItem[deeperKey] = item[key][deeperKey];
}
}
}
this.rows.push(newItem);
}
this.isJson(true);
});
I used another stackoverflow post (which I can't find right now) for the nested rows. Obviously flatting the sub-rows is not what I want but it can easily be changed.
It's my first typescript/html program :)
Thanks Again!

angularJS communicating with API

hi i am new completely new to AngularJS.
Trying to communicate with a JSON API. The API is beign called i am getting results bit the results are not getting filled into the view.
Here is the view:
<div >
<div data-ng-repeat="order in ordersResult.orders">
{{error}}
<fieldset class="fieldset">
<legend>
<b>{{order.klant.straat}} {{order.klant.huisnummer}} - {{order.klant.bedrijf}}</b>
</legend>
<table class="table table-bordered table-striped table-hover">
<th>Broodje</th><th>Aantal</th>
<tr data-ng-repeat="(tag,aantal) in order.broodjes" data-ng-click="check()">
<td>{{tag}}</td><td>{{aantal}}x</td>
</tr>
<tr data-ng-repeat="(tag,opmerkingen) in order.broodjesSpeciaal">
<td>{{tag}}</td><td><span ng-repeat="opmerking in opmerkingen">1x {{opmerking}}<br></span></td>
</tr>
</table>
</fieldset>
</div>
</div>
Here is the Controller:
app.controller('BezorgController', function ($scope, $resource) {
function getToday(){
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1;
var yyyy = today.getFullYear();
if(dd<10){dd='0'+dd} if(mm<10){mm='0'+mm}
//return mm+""+dd+""+yyyy;
return "22052013";
}
$scope.ordersRequest = $resource('http://www.movieapphd.com/bertus/api.1.0.0/order/bezorging/:day?key=:key',
{day: getToday(), key: API_KEY },
{get: {method: "JSONP"}}
);
$scope.ordersResult = $scope.ordersRequest.get();
if($scope.ordersResult.size == 0){
$scope.error = "Geen bezorgingen vandaag";
}
});
Here is the json that i get:
{
"orders":[
{
"klant":{
"bedrijf":"X",
"straat":"Haarlemmer",
"huisnummer":"8"
},
"broodjes":{
"0.0":0
},
"broodjesSpeciaal":{
"0.0":[
"nothing"
]
}
},
{
"klant":{
"bedrijf":"Anouk Beauty Gangbang",
"straat":"Haarlemmer",
"huisnummer":"220"
},
"broodjes":{
"0.0":0,
"1.1":2,
"1.2":1,
"2.3":1
},
"broodjesSpeciaal":{
"0.0":[
"nothing"
]
}
},
{
"klant":{
"bedrijf":"Hans Kazan GoochelTrucs",
"straat":"Haarlemmer",
"huisnummer":"222"
},
"broodjes":{
"0.0":0,
"1.1":2,
"1.2":2,
"2.3":1,
"3.1":1
},
"broodjesSpeciaal":{
"0.0":[
"nothing"
],
"2.3":[
"zonder stukjes",
"met extra stukjes"
]
}
}
]
}
What am i doing wrong here?
From the AngularJS docs, you can't use that syntax for arrays, and it appears sometimes broodjes and broodjesSpecial are arrays, and sometimes associative arrays. Also, in the one case where broodjes is an associative array there are no keys.
needed to change the method to get since the API is located on the same server.