I have a backbone model that I'm trying to extract specific values from. Something like: (using raw Object but assume its a backbone Model)
var x = {
primary : ["a","b","c"],
attributes : {
a : 1,
b : 2,
d : 4
}
}
In the end, it should render 1 2
I'm thinking something like
{{#each primary}}
{{#if attributes[this]}}{{attributes[this]}}{{/if}}
{{/each}}
but that doesn't seem to work. Ideas?
There is lookup helper made for it:
The lookup helper allows for dynamic parameter resolution using Handlebars variables. This is useful for resolving values for array indexes.
var source = $("#template").html();
var template = Handlebars.compile(source);
var data = {
primary : ["a","b","c"],
attributes : {
a : 1,
b : 2,
d : 4
}
};
$('body').append(template(data));
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.11/handlebars.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script id="template" type="text/x-handlebars-template">
{{#primary}}
{{lookup ../attributes this}}
{{/primary}}
</script>
Related
In my AngularJS web app, How can I query a JSON object ?
For example in the below JSON object how can I find the value of reportTypeLabel where reportTypeId=3
JSON:
[
{
reportTypeId:5,
reportTypeCode:"FINREP",
reportTypeLabel:"Financial Reporting"
},
{
reportTypeId:9000002,
reportTypeCode:"REM HE",
reportTypeLabel:"High Earners"
},
{
reportTypeId:3,
reportTypeCode:"COREP LE",
reportTypeLabel:"Large Exposures - COREP"
}
]
You can require $filter service and do
var elements = $filter('filter')(arrayOfObjects,{reportTypeId: 3});
elements will be an array of all the elements with that 'reportTypeId'
i would recommend reading about angular filters and https://docs.angularjs.org/api/ng/service/$filter
If you're going to use data manipulation extensively, I'd highly recommend using a JS library, like underscore or lodash.
For example, using underscore:
// assuming your object is called data
var result = _.findWhere(data, {
reportTypeId: 3
}).reportTypeLabel;
// result === 'Large Exposures - COREP'
You could do this
<div ng-repeat="report in reports | filter:{reportTypeId:'3'}">
{{report.reportTypeCode}}
</div>
Working Fiddle
You can use regular filter function on array:
var items = [
{reportTypeId:5, reportTypeCode:"FINREP"},
{reportTypeId:9000002, reportTypeCode:"REM HE"}
];
var onlyMatching = items.filter(function(item){ return item.reportTypeId == 3; });
Or an angular filter in html
<div ng-repeat="item in items | filter: {reportTypeId: '3'}">{{item. reportTypeLabel}}</div>
Or an angular filter through $filter service
module.controller('ItemsCtrl', function($filter){
$scope.filtered = $filter('filter')($scope.items,{ reportTypeId: '3' });
});
I am using dir-pagination directive by #michaelbromley. I want to get all the records on the current page of directive. Is there any way to do this?
Here is the link: dir-pagination, so I need a collection of 5 records from 100 to 96. Is there any quick way to do it?
I have tried couple of things but not working.
I ran into this same issue, but the answers here didn't fulfill my needs (or maybe wants). I decided to solve it myself, and settled on creating a filter whose sole purpose is to record the items passing through it in a given property on a given target. I came up with this:
/**
* Author: Eric Ferreira <http://stackoverflow.com/users/2954747/eric-ferreira> ©2015
*
* This filter will sit in the filter sequence, and its sole purpose is to record
* the current contents to the given property on the target object. It is sort of
* like the 'tee' command in *nix cli.
*/
angular.module('app').filter('record', function() {
return function(array, property, target) {
if (target && property) {
target[property] = array;
}
return array;
}
});
Then you use the filter in your pagination (or anywhere you want to get the current array actually [think, after filtering with a search query, after paging, after filtering current page, et cetera]) like so:
<div dir-paginate="item in items | itemsPerPage:pageSize | record:'currentPage':this">{{item.text}}</div>
You can also use it multiple times in one sequence:
<div dir-paginate="item in items | filter:searchQuery | record:'filtered':this | itemsPerPage:pageSize | record:'currentPage':this">{{item.text}}</div>
The above would record both the current page and all records resulted from the current filter query.
This will record (and update whenever it changes) the current page in $scope.currentPage. The this in the above example is the target of the filter. It resolves to $scope.this which, for most intents and purposes, is just $scope.
In your specific case, you would use this line (after adding/requiring the filter in your module) instead for your pagination:
<li dir-paginate="meal in perman = ( meals | filter:q ) | orderBy: order?'key':'-key' | itemsPerPage: pageSize | record:'currentPage':this">{{ meal.key + ': ' +meal.val }}</li>
I went ahead and forked your plunker to show it working too:
http://plnkr.co/edit/uC3RiC?p=preview
Here is another possible way to do it, which does not require you to duplicate the logic from the dir-paginate expression:
For each repeated item, you could just push that item into an array in your controller. This will of course give you all the items for that page.
Here is an example:
<ul>
<li dir-paginate="meal in perman = ( meals | filter:q ) | orderBy: order?'key':'-key' | itemsPerPage: pageSize" current-page="currentPage" ng-init="addMeal(meal)">{{ meal.key + ': ' +meal.val }}</li>
</ul>
Then in the controller:
$scope.addMeal = function(meal) {
if (meal) {
if ($scope.page.length === $scope.pageSize + 1) {
$scope.page = [];
}
$scope.page.push(meal);
}
}
I've not expensively tested it, but the general principle should work. It's a bit hacky in my opinion, but it's worth knowing as an alternative to the answer provided by Rathish.
Yes we can create our own logic according to data.
Displaying {{ pageSize * (currentPage-1)+$index+1 }} - {{ pageSize*currentPage }} of {{ perman.length }}
You can use array slice method since you already have access to the large array, know which page number you are on and know the number of elements per page. You can reuse the getPage function in the below code to achieve this.
app.js
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.currentPage = 1;
$scope.pageSize = 5;
var meals = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15];
function getPage(currentPage, pageSize, arr, reverse) {
var beginIndex, endIndex, noOfPages;
if(reverse) {
beginIndex = arr.length - currentPage * pageSize;
} else {
beginIndex = currentPage * pageSize - pageSize;
}
endIndex = beginIndex + pageSize;
beginIndex = beginIndex < 0 ? 0 : beginIndex;
return arr.slice(beginIndex, endIndex);
}
//This will return the 5 elements in page 1 of meals array which will be meals 11 to 15 since the array is bound to the pagination directive in the reverse (desc) order
$scope.firstFiveArrRev = getPage($scope.currentPage, $scope.pageSize, meals, true);
//This will return the 5 elements in page 1 of meals array which will be meals 1 to 5 since the array is bound to the pagination directive in ascending order
$scope.firstFiveArr = getPage($scope.currentPage, $scope.pageSize, meals, false);
});
index.html
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.0-rc.0/angular.js" data-semver="1.4.0-rc.0"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
Displaying elements from page number {{currentPage}}
<br />
Page size is set to {{pageSize}}
<br />
When order is Reverse: true
<div>{{ firstFiveArrRev.toString() }}</div>
When order is Reverse: false
<div>{{ firstFiveArr.toString() }}</div>
</body>
</html>
Here is the plnkr
http://plnkr.co/edit/CgH1WFR1JvOLmQsacVoI?p=preview
Download dirPagination.js from here.
Now include dirPagination.js to your page.
Add angularUtils.directives.dirPagination in your module like this
var app = angular.module("myApp",['angularUtils.directives.dirPagination']);
We use dir-paginate directive for pagination ,add dir-paginate in tr tag
<tr dir-paginate="event in events|orderBy:['columnid', 't']:true | itemsPerPage: 5">
Add below given code anywhere on your page or where ever you want.
<dir-pagination-controls
max-size="5"
direction-links="true"
boundary-links="true" >
</dir-pagination-controls>
I have a DateTime that is rendering in the grid via ClientTemplate() like this:
/Date(1294030800000)/
I know it is a valid date.
Has anyone seen this or can provide a clue as to what I am doing wrong?
Here is what I did (thanks to SLaks for pointing out that it was a JSON date) which reminded me that the Telerik grid serializes responses as JSON when in Ajax mode.
I created a helper function in my view:
<script type="text/javascript" language="javascript">
function ConvertToDateFromJSON(jsonDate) {
var regex = /-?\d+/;
var numbers = regex.exec(jsonDate);
var d = new Date(parseInt(numbers[0]));
return d;
}
</script>
And then the call to ClientTemplate goes like this:
columns.Bound(model => model.DateAdmitted)
.Template(o => o.DateAdmitted.ToString("d"))
.ClientTemplate(
"<#= $.telerik.formatString('{0:MM/dd/yyyy}', ConvertToDateFromJSON(DateAdmitted)) #>"
);
Having a array like below
var arrNames = ["Stackoverflow","StackExchange","Webmaster","Programmers"];
how should a template look for working with mustache.js javascript template. I tried below but no clues
{{#}}{{key}}{{/}}
From the documentation:
When looping over an array of strings, a . can be used to refer to the current item in the list.
Template:
{{#musketeers}}
* {{.}}
{{/musketeers}}
View:
{
"musketeers": ["Athos", "Aramis", "Porthos", "D'Artagnan"]
}
Output:
Athos
Aramis
Porthos
D'Artagnan
var tpl = document.getElementById('simple').innerHTML,
view = {
items: ['Stackoverflow', 'StackExchange', 'Webmaster', 'Programmers']
};
document.getElementById('output').innerHTML = Mustache.to_html(tpl, view);
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.js"></script>
<script type="template" id="simple">
<h1>Array Values</h1>
<ul>
{{#items}}
<li>{{.}}</li>
{{/items}}
</ul>
</script>
<div id="output"></div>
Using Ember.js I get an endless loop with the following code:
Controller:
App.activityDetailsController = Em.Object.create({
activityBinding : 'App.navController.selectedActivity',
data : function(){
var things = new Array();
if(this.activity){
var info = this.activity.get('info');
var len = info.length;
for(var i=0; i<len; i++){
for(prop in info[i]){
things.push({"key": prop, "value" : info[i][prop]});
}
}
}
return things;
}.property('activity')
})
View:
App.ActivityDetailsView = Em.View.extend({
templateName : 'activity-details',
activityBinding : 'App.activityDetailsController.activity',
dataBinding : 'App.activityDetailsController.data'
})
Template:
<script type="text/x-handlebars" data-template-name="activity-details">
<div id="info">
{{#each data}}
{{key}}: {{value}}<br />
{{/each}}
</div>
</script>
When trying to load this page, the 'data' function in the controller is called endlessly.
If I remove the {{#each}}{{/each}} block from the view, there is no problem and using {{data.length}} in the template gives the correct output.
Any ideas why this loops endlessly? If I remove 'activity' from the property call, it the problem is the same.
Thanks,
Make your "data" property cacheable(). See ebryn's answer to a related question for the reason why.