I'm trying to bind a late calculated field to my ui with not much of success, This is my controller -
PaymentsController = ['$scope', 'Payment','Campaign', ($scope, Payment,Campaign)->
Payment.query().then((payments) ->
$scope.payments = payments
angular.forEach($scope.payments,(payment,index)->
payment.from = $scope.getFrom(payment)
)
The concept is simple, but the method getFrom returns a promise, when i get to this controller i load a list, the ui looks like this:
<table>
<tr>
<th ng-bind="'from'|i18n"></th>
<th ng-bind="'amount'|i18n"></th>
<th ng-bind="'to'|i18n"></th>
<th ng-bind="'description'|i18n"></th>
</tr>
<tr ng-repeat="payment in payments">
<td ng-bind="payment.from"></td>
<td>{{getAmount(payment)}}</td>
<td>{{getTo(payment)}}</td>
<td>{{getDescription(payment)}}</td>
</tr>
<tr ng-show="!payments.length">
<td ng-bind="'no_payments'|i18n"></td>
</tr>
</table>
nothing fency,
all fields are bind as expected except the from, according to controller i expect to see "asd"
but i see nothing.
I need to return a promise in this method but first I'm trying to make it work with simple code.
My problem was more conceptual I guess, I managed to fix this by making the controller control the view and not the view to control the controller, so instead of assigning a promise to the "from" field, I declared it when I had a value to put in, so my code looks like this:
angular.forEach($scope.payments, (payment, index)->
$scope.resolveFrom(payment)
)
$scope.resolveFrom = (payment)->
if payment.amount < 0
payment.from = "1"
else if payment.campaign_id
Campaign.get(payment.campaign_id)
.then((campaign)->
payment.from = campaign.name)))
payment.from = "unkown"
I'm not sure if this is the best practice, would appreciate comments/alternative solutions.
Related
I already used ngTable with static data before, it worked well (listing, sorting and filtering). I'm using ngTable v 0.8.3
My Goal
This time I want to create a ngTable with data loaded from a Web Service.
I made a custom factory to be able to create my ngTable with future others entities.
Issue
It doesn't work and I have no JS console errors. When I debug, I can clearly see that my method query from my service Employee return me my complete and correct objet containing employees details. I enter in the getData() function, the ngTable is being created, but with empty data.
Relevant and lightweighten code
Here is my HTML markup :
<table ng-table="tableParams" class="table table-striped" show-filter="true">
<tbody>
<tr ng-repeat="employee in $data">
<td data-title="'employee.firstname' | translate" filter="{'firstname' : 'text'}" sortable="'firstname'"><a ui-sref="employee.detail({id:employee.id})">{{employee.firstname}}</a></td>
<td data-title="'employee.lastname' | translate" filter="{lastname : 'text'}" sortable="'lastname'">{{employee.lastname}}</td>
<td data-title="'employee.mail' | translate" filter="{mail : 'text'}" sortable="'mail'">{{employee.mail}}</td>
<td data-title="'employee.phone-number' | translate" filter="{phone_number : 'text'}" sortable="'phone_number'">{{employee.phone_number}}</td>
<td data-title="'employee.birthdate' | translate" filter="{birthdate : 'text'}" sortable="'birthdate'">{{employee.birthdate}}</td>
</tr>
</tbody></table>
my Angular controller :
myapp.controller('EmployeeController', function ($rootScope, $scope, Employee, ngTableParams, ngTableFactory) {
$scope.tableParams = ngTableFactory.create(20, {lastname: 'asc'}); // count, sorting
});
And my Angular factory :
myapp.factory('ngTableFactory', function(ngTableParams, Employee) {
return {
create: function(count, sorting) {
return new ngTableParams({
page: 1, // initial page
count: count, // count per page
sorting: sorting // initial sorting
}, {
total: 0,
getData: function($defer, params) {
Employee.query({page: params.page(), size: params.count()}, function(result) {
$defer.resolve(result);
});
}
});
}
}
});
Edit 1, progresses :
My items are being listed if I remove params from my query method, so it was a bad handling of my Employee service. But, the sort and filter does not work on my table by default. to make sorting works, I have to add this line on my ngTable factory, in the getData() function :
result = $filter('orderBy')(result, params.orderBy());
Normally, the sorting of basic elements works as I added the 'sortable' keyword in my HTML ngtable template columns, and as I'm fetching my data over $data item. Still investigating.
Thanks for your help mates !
As far as I can see, your code works.
Please see https://github.com/masa67/NgTable for a working example (based on Node). I did not change anything (except filled-in the missing parts, maybe the problem is there).
The table formatting is not correct, but at least the data is coming in.
I have developed a ngtable with a filter. The pagination on the table does not work anymore though? When I select the show 10 rows on the bottom of the table it still shows 14 rows? How can i fix the pagination/indexing?
This is my table definition:
<table ng-table="tableParams" class="table">
<tr ng-repeat="account in $parent.filtered =(data | filter:search.accountName | filter:search.id)">
<td data-title="'id'">
{{account.account.accountId.id}}
</td>
<td data-title="'name'">
{{account.account.accountName}}
</td>
</tr>
</table>
plunkr:http://plnkr.co/edit/Rqt6px?p=preview
You need to figure pagination function by yourself. You may see ng-table's example in here.
var Api = $resource("/data");
this.tableParams = new NgTableParams({}, {
getData: function(params) {
// ajax request to api
return Api.get(params.url()).$promise.then(function(data) {
params.total(data.inlineCount); // recal. page nav controls
return data.results;
});
}
});
It first load all the data into Api. The params.url() contains current page and page count. It then use these two variable to return part of dataset. So you may need to figure out how to return this part of data.
I want to show a list of elements on view asynchronously.
For example i have a method which returns promise and result will look like this.
var result = {
books: [
{name: 'The Kite Runner', author: 'Khaled Hosseini'},
{name: 'The Book Thief', author: 'Markus Zusak'},
{name: 'A Thousand Splendid Suns', author: 'Khaled Hosseini'},
]
}
Here is a method:
function getBooks(userId) {
return BookProduct.getBooksByUser.query({ id: userId }).$promise;
};
And then i have a method which invokes getBooks.
$scope.showBooks = function(userId) {
//some users id
var users_id = [1,2,3,4,5];
$scope.tables = [];
for (i = 0; i < users_id.length; i++) {
getBooks(i).then(function(result){
$scope.table = {
books = result;
}
$scope.tables.push($scope.table);
})
}
}
Thereafter i want to show it to user on a view using angular ng-repeat.
<div data-ng-repeat="table in tables">
<table>
<thead>
<tr>
<th>Name</th>
<th>Author</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="book in table.books">
<td>{{ name }}</td>
<td>{{ author }}</td>
</tr>
</tbody>
</table>
</div>
It works good but ng-repeat will work when function $scope.showBooks is executed and $scope.tables is already full. I am looking for more nice solution. I want to load books for user piecemeal on each iteration when method getBooks() invokes.
So in this part for example when the first iteration is processing and i get result of 2 elements, then i pass them to the view and user can see the first part. Next iteration i get for example other 3 elements, so i add them to previous result and pass to the view, so user can see 5 elements now, and so on. I know it will be almost insensibly for user but if my server responds slowly it will help me to be more user friendly.
for (i = 0; i < users_id.length; i++) {
getBooks(i).then(function(result){
$scope.table = {
books = result;
}
$scope.tables.push($scope.table);
})
}
I am not asking you HOW to implement it. I just want to know is it possible or not and where should i dig to know more, cause i tried some googling but without success.
Angular has a cycle in which it performs all scope functionality and after each cycle of "watches" it renders changes to the view. By default, Angular performs this automatically - for example simple change of variable in scope also rerenders view. But in some cases you may want to intercept because your operation didn't trigger the rerender.
For these cases, $apply and $digest are useful - more in documentation https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$apply
First off please don't bash me for using old technology (polling) and an old version of Mootools (1.3.2) as I don't have control over these factors.
Ok here's my problem.
I have a page which refreshes every few seconds to fetch new data from the database via AJAX. Ideally the structure of the returned value should be as such:
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
After receiving this table row structure result, I need to append that to the current table in the page which essentially just adds a new record on the table if there are new records. If there's none, then no changes to the table are made.
Currently I am using
var req = new Request.HTML({url: url_to_get_new_rows,
onSuccess: function(html, responseHTML) {
// append table row 'html' here
}
}).send();
However, the returned value in the 'html' variable that I'm supposed to append at the end of the table only returns
1 2 3 4
This obviously is an undesired behavior as I need the tr and td elements to make it work.
I hope someone could help me with this problem.
THANKS!
Javascript:
new Request.HTML({
url:'tr.php',
onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript) {
var tbody = document.id('tbody');
tbody.set('html', tbody.get('html') + responseHTML);
// or
var tr = new Element('table', {'html': responseHTML}).getElement('tr');
tr.inject(tbody);
}
}).get();
HTML:
<table>
<thead>
<tr>
<th>1</th>
<th>2</th>
<th>3</th>
<th>4</th>
</tr>
</thead>
<tbody id="tbody">
<tr>
<td>a</td>
<td>b</td>
<td>c</td>
<td>d</td>
</tr>
</tbody>
</table>
I've got an AngularJS webapplication where I use ng-repeat on an array of persons. The json array defines a firstname, lastname and age of the persons.
In my table I'm trying to apply a CSS class to all the young persons using the ng-class directive.
<table class="table table-striped table-hover">
<tr><th>Firstname</th><th>Lastname</th><th>Age</th></tr>
<tr ng-repeat="person in people | filter:search" ng-class="{success: person.isYoung()}">
<td>{{person.firstname}}</td>
<td>{{person.lastname}}</td>
<td>{{person.age}}</td>
</tr>
</table>
Notice I'm trying to call person.isYoung(), which is the method I'm having trouble with. Things work if I use
ng-class="{success: person.age < 30}"
but, I want to move that logic into the Controller instead.
Inside my Controller I've added this;
$scope.isYoung = function (person) {
return person.age < 30;
}
but it seems like that isn't called.
What should my method definition in app.js look like for me to get this working?
ng-class="{success: person.isYoung()}"
The signature of the function is
isYoung(person)
So that's what you need to use in your template:
ng-class="{success: isYoung(person)}"
If you want to be able to use person.isYoung(), then you need to add this function to all the persons in the array :
angular.forEach(persons, function(person) {
person.isYoung = function() {
return person.age < 30;
}
});