AngularJS ng-repeat messing up with order - angularjs-ng-repeat

I have created an Javascript object the following way:
$scope.initNews = function () {
for (var i = 2013; i > 2000; i--) {
$scope.news[i] = {};
$scope.news[i]["year"] = Number(i);
for (var j = 1; j <= 12; j++) {
$scope.news[i][j] = {};
$scope.news[i][j]["month"] = $scope.month_names[j-1];
}
}
};
but ng-repeat seems to mess up with the way it loops through the items.
<ul ng-repeat="old_news_year in news">{{old_news_year.year}}
<li ng-repeat="old_news_month in old_news_year">{{$index + 1}}. {{old_news_month.month}}</li>
</ul>
For the whole sample, check http://jsfiddle.net/tFewZ/1/
EDIT I am under the impression (by adding a "debugger;" into the code)
that AngularJS is looping through the entries according to their
$$hashKey and not according to their Javascript index...
Still do not understand about the 13th element though... is this the prototype attribute?
Thanks in advance.
Best regards,
Guillaume

Solution is to use $index instead of the collection approach ('in').
<ul ng-repeat="old_news_year in news">{{old_news_year.year}}
<li ng-repeat="old_news_month in old_news_year">
{{$index + 1}}. {{old_news_year[$index+1].month}}
</li>
</ul>
Check: http://jsfiddle.net/guillaume1978/XmSTK/2/

Related

Angular2 - Table using *ngFor with paging and sorting

I am creating a simple html table with *ngFor in Angular 2.
My question is,
Is there an easy way to add sorting and paging to the same table without using any additional third party JavaScript ?
Does angular2 provide any techniques to achieve the same ?
I have been attempting to dynamically build and paginate my table in angular without the use of a 3rd party library. Some considerations around this desire may include some or more of the following:
Number of items per table-page. Do you want user to specify them or hard-corded?
Handling the click events, i.e. First,<>Last
The following code I used to dynamically generate the pages number (P2,...,Pn)
declare a variable (pagenumbers) to hold the page number HTML
pagenumbers = '<li class="page-item disabled clearfix d-none d-md-block"><a class="page-link waves-effect waves-effect">First</a></li><li class="page-item-disabled"><a class="page-link" aria-label="Previous"><span aria-hidden="true">«</span><span class="sr-only">Previous</span></a></li><li class="page-item active"><a class="page-link">1</a></li>';
Calling a service to get list of customers:
async getCustomerOrders(CustomerID: number, customerService: CustomerService) {
await customerService.getCustomerOrders(CustomerID)
.map((res) => res)
.subscribe(
data => {
this.customerOrders = data;
this.tot = this.customerOrders.length;
console.log('Total records: ' + this.tot);
this.workingWithLoop(this.tot / 10);
},
err => console.log(err),
() => console.log(this.customerOrders.length / 10)
);
}
The page numbers:
workingWithLoop(pages: number) {
// let pageNumbers = '';
console.log(this.pagenumbers);
console.log('Total pages: ' + pages);
for (let n = 2; n < pages; n++ ) {
console.log('Value of n: ' + n);
this.pagenumbers += '<li class="page-item"><a class="page-link waves-effect waves-effect">' + n + '</a></li>';
}
// tslint:disable-next-line:max-line-length
this.pagenumbers += ' <!--Arrow right--><li class="page-item"><a class="page-link" aria-label="Next"><span aria-hidden="true">»</span><span class="sr-only">Next</span></a></li><!--First--><li class="page-item clearfix d-none d-md-block"><a class="page-link">Last</a></li>';
}
In my html use the following code at the bottom of the table for the page numbers
<nav class="my-4 pt-2">
<ul class="pagination pagination-circle pg-purple mb-0" [innerHTML]="pagenumbers">
</ul>
</nav>
I am still working on dynamically generating a paginated table paginated table.
Angular does not have built-in way to sort tables. You will either have to do it yourself with wiring the events in the table headers, or use a third party component. PrimeNG does this and much more.
Update:
If you wanted to do this yourself, the equivalent of "filters" (Angular 1) is pipes in Angular 2. Here is good guide: http://voidcanvas.com/angular-2-pipes-filters/

Angular-JS. How to make controllers work inside ng-repeat with ng-show

I am very new at Angular and I am trying to make something where if you click a tab, ng-repeat will show everything with a certain property and if you click a different tab, ng-repeat witll show everything with a different property. However I cant get the tab controller to work along with ng-show. Here is my code:
<ul class = "nav nav-pills" ng-controller = "TabController as tabCtrl">
<li ng-class="{'active':tabCtrl.isTab(1)}">
<a ng-click="tabCtrl.setTab(1)" href = "#"> All </a>
</li>
<li ng-class="{'active':tabCtrl.isTab(2)}">
<a ng-click="tabCtrl.setTab(2)" href = "#"> Online </a>
</li>
<li ng-class="{'active':tabCtrl.isTab(3)}">
<a ng-click="tabCtrl.setTab(3)" href="#"> Offline </a>
</li>
</ul>
...
<div class = "user" ng-repeat="streamer in twitch.users" ng-show="tabCtrl.isTab(1)">
//... repeated stuff here
</div>
Here is the js code for TabController:
app.controller('TabController', function(){
this.tab = 1;
this.setTab = function(t){
this.tab = t;
}
this.isTab = function(t){
return (this.tab == t);
}
})
However ng-show shows nothing as isTab() is always false. Can anyone explain to me why?
Use the pattern I referred to in the comments to keep a reference to the controller object. This is how you might do it using the "controller as" syntax in AngularJS:
app.controller('TabController', function(){
var self = this;
this.tab = 1;
this.setTab = function(t){
// inside a function "this" is not the controller
// it is a reference to the function
self.tab = t;
};
this.isTab = function(t){
return (self.tab == t);
};
})

Rivetsjs iteration - by using an integer instead of collection

According to rivetsjs docs, we can render content by iterating over a object (array) by,
<ul>
<li rv-each-todo="list.todos">
<input type="checkbox" rv-checked="todo.done">
<span>{ todo.summary }</span>
</li>
<ul>
but is there a way where I can iterate by using a single integer to indicate number of times the iteration to take place?
I mean something like this,
<li rv-each="list.num_of_todos">
...
where num_of_todos is an integer to indicate number of iterations to take place.
There is no "proper" way of doing it. However, you can easily mimic this using a formatter that returns an array as shown below:
var list = {
name: 'to do list',
noOfToDos: 5
};
rivets.formatters.makearray = function(value) {
var result = [];
while (value--) {
result.push(0)
};
return result;
}
rivets.bind($("ul"), { // bind rivets
list: list
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/rivets/0.7.1/rivets.bundled.min.js"></script>
<ul>
<li rv-each-item="list.noOfToDos | makearray">Test</li>
<ul>

Autoclosing unclosed tags in template

Hi i'm tring to create such template
<script type='text/mustache' id='user-template'>
<ul>
{{#each users}}
<li>{{name}}</li>
{{#startHidden #index 2}}</ul><ul style = "display:none;">{{/startHidden}}
{{#endHidden #index 2}}</ul>show all{{/endHidden}}
{{/each}}
</ul>
</script>
So the idea is to close the upper <ul> after second user in list open new hidden <ul> and put all rest users here. But instead i got closed <ul> and final html looks like:
<ul>
<li>name1</li>
<li>name2</li>
<ul style="display:none;"></ul>
<li>name3</li>
<li>name4</li>
show all
</ul>
This is my js
var data = [{name: "name1"},{name: "name2"},{name: "name3"},{name: "name4"}];
var users = new can.List(data);
var frag = can.view("user-template",{users:users},{
'startHidden' : function(currentIndex, usersToShow, options){
if (currentIndex() === usersToShow-1) {
return options.fn(this);
}
},
'endHidden' : function(currentIndex, usersToShow, options){
var length = options.scope.attr('users').length;
if ((length>usersToShow)&&(currentIndex() === length-1)) {
return options.fn(this);
}
}
});
Is there any way to prevent auto closing tags, or may i'm just doing it wrong completely?
This is not possible. can.view.live.html can only remove or add elements in sequence. A workaround would be to just add a "hidden" class on an LI if it shouldn't be visible.

ASP.NET MVC 3 how can I create dynamic attribute name in view in cshtml?

In MVC 3, view-cshtml file, I want to create a dynamic id like below. How can I merge "videoItem_" and "#MenuItemIndex" to get "videoId_5" for example?
<div class='videoItem' id='videoItem_#MenuItemIndex'>
EDIT : I only need to add();
<div class='videoItem' id='videoItem_#(MenuItemIndex)'>
Thank you.
Wrap the variable in brackets to make the expression explicit:
<div class='videoItem' id='videoItem_#(MenuItemIndex)'>
#for(int i = 0; i < SomeInteger; i++){
<div class='videoItem' id='videoItem_#(i)'>
}

Resources