Pagination with Handlebars/Backbone - javascript

I want to implement a simple pagination using Handlebars. I am using bootstrap 3. This is what I have:
HTML
<div class = "categories-block">
{{#each category}}
<div class = "category">
<div class = "item">
<h2>{{itemname}}</h2>
View Category
<p class = "item-desc">{{itemndesc}}</p>
</div>
</div>
{{/each}}
</div>
<div class="pagination">
<li>Previous</li>
<li>1</li>
<li>Next</li>
</div>
MODEL
var categorymodel = Backbone.Model.extend({
url: "http://localhost/category.json",
defaults: {
}
});
Right now, everything I get from my model is displayed there. How can I paginate, display 5 items in one page.
Thanks in advance

Related

How to target an item inside ngFor with introjs

I need to use introjs to tour new features on an angular 6 app.
Inside the tour some step target items in ngFor in a child component of the component where I start introjs. The library is able to target child component html elements but seems to not be able to target element inside ngFor. The usage I want is simple I have a li that represent a card item I loop on as :
<div *ngFor="let source of sourcesDisplay; let idx = index" class="col-lg-5ths col-md-4 col-sm-6 col-xs-12">
<!-- item -->
<div class="item blue-light">
<div class="header">
<div class="categories">
<div class="truncat">{{source.categories.length > 0? source.categories : 'NO CATEGORY'}}</div>
</div>
<a routerLink="{{ organization?.name | routes: 'sources' : source.id }}" class="title">
<div class="truncat">{{source.name}}</div>
</a>
<div class="corner-ribbon blue-light" *ngIf="isARecentSource(source.createdAt)">New</div>
<div class="corner-fav" [class.is-active]="isSourceFavorite(source.id)"
(click)="toggleFavorite(source.id)"><em class="icon-heart-o"></em></div>
</div>
<a class="content" routerLink="{{ organization?.name | routes: 'sources' : source.id }}">
<div class="icon">
<em [ngClass]="source.icon? 'icon-'+source.icon : 'icon-cocktail3'"></em>
</div>
</a>
<div class="actions">
<ul class="buttons three">
<li class="icon-font" ><a (click)="openDashboardModal(source)"
[class.disable]="source.powerbi.length === 0" class="btn-effect"><em
class="icon-chart-bar"></em></a></li>
<li class="icon-font"><a
(click)="openDatalakeModal(source)" [class.disable]="source.datalakePath.length === 0"
class="btn-effect"><em class="icon-arrow-to-bottom"></em></a>
</li>
<li class="icon-font"><a routerLink="{{ organization?.name | routes: 'sources' : source.id }}"
class="btn-effect"><em class="icon-info-circle"></em></a></li>
</ul>
</div>
</div>
</div><!-- /item -->
And I want to target part of this card like a button for example as :
<li class="icon-font" id="step4{{idx}}">
<a (click)="openDashboardModal(source)" [class.disable]="source.powerbi.length === 0" class="btn-effect">
<em class="icon-chart-bar"></em>
</a>
</li>
and then in my component :
const intro = IntroJs.introJs();
intro.setOptions({
steps: [
{
element: document.querySelector('#step40'),
intro: 'Welcome to the Data Portal ! Explore and download data accross any division. Let\'s discover the new home page.'
}]})
intro.start();
Is there something I am doing wrong ? is introjs not able to do it at all ? is there another lib that can do it?
Thank you in advance
The sections generated by the *ngFor loop may not be rendered yet in the AfterViewInit event. To detect the presence of these elements, you should use #ViewChildren and monitor the QueryList.changes event.
In the template, define a template reference variable #step instead of id:
<li class="icon-font" #step>
<a (click)="openDashboardModal(source)" [class.disable]="source.powerbi.length === 0" class="btn-effect">
<em class="icon-chart-bar"></em>
</a>
</li>
In the code, retrieve the elements with #ViewChildren, and subscribe to the QueryList.changes event. You may have to convert the QueryList to an array to access an element with a specific index.
#ViewChildren("step") steps: QueryList<ElementRef>;
ngAfterViewInit() {
this.startIntroJs(); // Maybe already present
this.steps.changes.subscribe((list: QueryList<ElementRef>) => {
this.startIntroJs(); // Created later
});
}
private startIntroJs(): void {
if (this.steps.length > 40) {
const intro = IntroJs.introJs();
intro.setOptions({
steps: [
{
element: this.steps.toArray()[40].nativeElement,
intro: 'Welcome to the Data Portal...'
}
]
});
intro.start();
}
}

How do I dynamically show more bootstrap tabs in a _Layout template?

I have an existing site using MVC and a _Layout page using a sectional control for the render. We are using bootstrap tabs throughout for data displays.
I have simplified this setup, but there are other VMs binding to this page, so I can't bind to the whole page, which would be the easy route for what I need.
I want to have a dynamic amount of tabs being rendered like:
<div class="panel panel-default">
<div id="tabContentParent" class="tab-content">
<div class="tab-pane active" id="result">
<!-- various details of a report -->
</div>
<!-- ko foreach: myVM -->
<div class="tab-pane" data-bind="attr: {'id': reportId}">
<!-- various bindings for reports -->
</div>
<!-- /ko -->
</div>
</div>
#section scripts
{
#Scripts.Render("~/Areas/Results/VMs/myVM.js")
<script type="text/javascript">
app.myVM.load();
ko.applyBindings(app.myVM, document.getElementById('tabContentParent'));
</script>
}
How can I get the tabs to also reproduce like this when they are in a separate sectional control and not within the same data-binding area?
#section controls
{
<ul class="nav nav-tabs section-controls">
<li class="active">Details</li>
<li class="hidden" id="tab1">Report 1</li>
<li class="hidden" id="tab2">Report 1</li>
<!-- etc., etc. -->
</ul>
}
I am not sure if this is the best way to do it, or if this is the best way to use knockout... but I think I have figured out how to do this. I have bound the ViewModel to multiple sections in separate applyBindings calls. I haven't seen this as a solution or suggestion before so I am not sure if there are side-effects.
A fiddle: Knockout multi-binding showing the functioning solution I propose. I defined the nav tabs like so:
<div>
<ul class="nav nav-tabs section-controls" id="vm1Id2">
<li class="active">Details</li>
<!-- ko foreach: tabInfos -->
<li>
<a data-bind="text: text, attr:{ href: '#' + url }" data-toggle="tab"></a>
</li>
<!-- /ko -->
</ul>
</div>
I defined the tab context like so (and a vm/div as a separator):
<div id="vm2Id">
<p>
<label data-bind="text: message"></label>
</p>
</div>
<div class="panel panel-default">
<div id="vm1Id1" class="tab-content">
<div class="tab-pane active" id="result">
<label>Some data displayed here</label>
</div>
<!-- ko foreach: newTabs -->
<div class="tab-pane" data-bind="attr: {'id': $data}">
<label data-bind="text: $data"></label>
</div>
<!-- /ko -->
</div>
</div>
And finally, I bound everything a little double time.
var ViewModel1 = function() {
var newTabs = ko.observableArray(["report1", "report2"]);
var tabInfos = ko.observableArray([{text: "Report 1", url: "report1"}, {text: "Report 2", url: "report2"}]);
return {
newTabs: newTabs,
tabInfos: tabInfos
};
};
var ViewModel2 = function() {
var message = ko.observable("This is a message as a space holder");
return {
message: message
};
};
var vm1 = new ViewModel1();
var vm2 = new ViewModel2();
ko.applyBindings(vm1, document.getElementById('vm1Id1'));
ko.applyBindings(vm1, document.getElementById('vm1Id2'));
ko.applyBindings(vm2, document.getElementById('vm2Id'));
I think this is the correct way to approach this. It works well enough when the page renders.

How to add data and data flow in Ionic App using angular js

In AngularJS I want to create a birthday card list where I select my friends list from my JSON file and fill date of my selected friends.
I show my friends list in my index.html as
<!-- immutable scripts added -->
<script src="js/immutable.min.js"></script>
<ion-content class="has-subheader" >
<!-- card list declaration -->
<ul class="card">
<!-- checkBox Declaration and filtering by search box -->
<li class="item item-thumbnale-left" ng-repeat="item in items | filter:query">
<!-- show friends list in cards -->
<input type="text" ng-model ="friend.Name"
ng-init = "friend.Name = item.Name" readonly/>
<!-- take a input field for taking friend b'day date -->
<div class="item item-input-inset">
<!-- click a checkbox for add friend -->
<label class="checkbox">
<input type="checkbox" ng-click ="saveOrDelBirthday(friend)"
ng-show = "friend.Date" ng-model = "friend.check"/>
</label>
<label class="item-input-wrapper">
<input type="date" placeholder="Enter Date"
ng-model = "friend.Date" />
</label>
</div>
</li>
</ul>
</ion-content>
when i click a show button then a new list.html shows all selected friends list with their birthday but
My selected friend list is not showing the list in
list.html file as
<ion-content>
<ul class="card">
<li class="item" ng-repeat="(key,value) in information">
<div style="float: left">{{ key }}</div>
<div style="float: center">{{ value }}</div>
</li>
</ul>
<label class="item">
// this is for sending mail to me from my app
<button class="button button-positive" type="submit" ng-click = "sendMailMe()" >Confirm</button>
</label>
I use immutable data structure for storing data with key value pair in immutable.Map({});
I don't know where i'm wrong.
//my controller contain this method
$scope.information = {}; //storing data from map
var friendMap = Immutable.Map({}); //declaring Map for inserting data in key value pair
$scope.friendMap1;
//this section decide which operation perform
$scope.saveOrDelBirthday = function(friend){
console.log(friend.check);
if(friend.check){
friendMap1 = friendMap.set(friend.Name,friend.Date); //insert friend information
}
else{
friendMap1 = friendMap.delete(friend.Name); //delete friend information
}
information = friendMap1.toObject();
console.log(information);
};
It looks like $scope.information expected by the ng-repeat directive isn't being defined in your controller or is returning an empty list/object.

Update page with items added via text field in Ember

I'm working on my first Ember app. It's a variation of a to do app. You type in a value, hit submission button and the page should update with each new item added using two-way data binding.
Every new item gets added to an array of object literals.
So adding new objects to the array and then looping through each item and printing it to the page is working just fine. Only problem is the page never updates with new items added via the input field.
I thought creating a custom view (App.ReRenderUserList in this instance) and adding .observes like they talk about in a previous question might be the answer, but that didn't seem to work.
Here's my code. Let me know if there's anything else I need to add. Thanks for your help.
index.html
<script type="text/x-handlebars" data-template-name="add">
{{partial "_masthead"}}
<section>
<div class="row">
<div class="column small-12 medium-9 medium-centered">
<form {{action "addToList" on="submit"}}>
<div class="row">
<div class="column small-8 medium-9 no-padding-right">
{{input type="text" value=itemName}}
</div>
<div class="column small-4 medium-3 no-padding-left">
{{input type="submit" value="Add +"}}
{{!-- clicking on this should add it to the page and let you keep writing --}}
</div>
</div>
<!-- /.row -->
</form>
</div>
<!-- /.column -->
</div>
<!-- /.row -->
</section>
<section>
<div class="row">
<div class="column small-12 medium-9 medium-centered">
<div class="list">
{{#each userItems}}
<div class="column small-16">
{{#view App.ReRenderUserList}}
<div class="item">{{name}}</div>
{{/view}}
</div>
<!-- /.column -->
{{/each}}
</div>
<!-- /.list -->
</div>
<!-- /.column -->
</div>
<!-- /.row -->
</section>
</script>
<!-- END add items template -->
pertinent app.js code:
var itemLibrary = [
{
'name' : 'bread'
},
{
'name' : 'milk'
},
{
'name' : 'eggs'
},
{
'name' : 'cereal'
}
];
var userLibrary = [];
App.AddRoute = Ember.Route.extend({
model: function() {
return Ember.RSVP.hash({
presetItems: itemLibrary,
userItems: userLibrary
});
}
});
App.AddController = Ember.ObjectController.extend({
actions: {
// add the clicked item to userLibrary JSON object
addToList: function(){
var value = this.get('itemName'); // gets text input value
userLibrary.push({
name: value // this is just echoing and not adding my new items from the form.
}); // adds it to JSON Object
console.log(userLibrary);
}
}
});
App.ReRenderUserList = Ember.View.extend({
submit: function(){
console.log('rerendered!');
}
});
You should use the pushObject method instead of the push method. This will update the bindings..
App.AddController = Ember.ObjectController.extend({
actions: {
// add the clicked item to userLibrary JSON object
addToList: function(){
var value = this.get('itemName'); // gets text input value
userLibrary.pushObject({
name: value // this is just echoing and not adding my new items from the form.
}); // adds it to JSON Object
console.log(userLibrary);
}
}
});

Metro Javascript. Error grouping items. ui.js firstItemIndexHint property

Well, I'm pulling my hair out with an error grouping items to render in a listview.
When I set the items/groups datasources to the list thru WinJS.UI.setOptions I get an error in ui.js at line 16812 saying "Unable to get property 'firstItemIndexHint' of undefined or null reference".
I have other pages in my application where grouping works fine but this one doesn't seems to work. I use the same binding method in all of them and I can't find any difference between them that causing this error.
Can anyone tell me what's making the following code crash?.
Thanks.
javascript page code in ready function:
var arr = new Array();
//fill in an array with sample data.
//name property is the one used for grouping
//nm is rendered in the item template.
for (var i = 0; i < 10; i++) {
arr.push({
name: "group" + (i % 5),
nm: "namer" + i,
});
}
//create a list based on the array.
var items = new WinJS.Binding.List(arr);
//group items by the name property (key selector function) and
//use it for rendering the group template (group data function)
var groupDataSource = items.createGrouped(
function (item) {
return item.name;
},
function (item) {
return {
name: item.name,
click: function () {
nav.navigate("mynavpage.html");
}
};
});
//get a reference to the listview control
var listView = element.querySelector(".itemGroups").winControl;
//set templates and datasources to listview
//here's where calls to base.js/ui.js are made and where app fails.
WinJS.UI.setOptions(listView, {
groupHeaderTemplate: $(".headerTemplate")[0],
itemTemplate: $("#itemTemplate1")[0],
itemDataSource: items.dataSource,
groupDataSource: groupDataSource.groups.dataSource,
});
html page code
<!-- group header template -->
<div class="headerTemplate" data-win-control="WinJS.Binding.Template" style="display: none">
<h2 class="group-title" data-win-bind="textContent: name" role="link">
</h2>
</div>
<!-- item template -->
<div id="itemTemplate1" data-win-control="WinJS.Binding.Template" style="display: none">
<div class="itemTemplate item1x1" id="item1">
<div class="itemText">
<h4 class="itemTitle win-type-ellipsis" data-win-bind="textContent: nm"></h4>
</div>
</div>
</div>
<!-- fragment section -->
<div class="myPage fragment">
<header aria-label="Header content" role="banner">
<button class="win-backbutton" aria-label="Back" disabled></button>
<h1 class="titlearea win-type-ellipsis">
<span class="pageTitle">Page Title</span>
</h1>
</header>
<section aria-label="Main content" role="main">
<!-- listview Grid -->
<div class="itemGroups" aria-label="List of groups" data-win-control="WinJS.UI.ListView"
data-win-options="{ tapBehavior: 'toggleSelect' }">
</div>
</section>
</div>
You need to use the groupDataSource for both the items and the groups.
WinJS.UI.setOptions(listView, {
groupHeaderTemplate: $(".headerTemplate")[0],
itemTemplate: $("#itemTemplate1")[0],
itemDataSource: groupDataSource.dataSource,
groupDataSource: groupDataSource.groups.dataSource,
});

Categories

Resources