How to execute function on the object inside the template - javascript

I have simple handlebar template:
'<h1>Order number: {{orderNumber}}</h1>'
That works fine.
Now I have situation where object that I pass it for render has a function to return itself id. It goes like this:
'<h1>Order number: {{orderNumber}}</h1><h2>Order ID:{{getId()}}</h2>'
How can I make Handlebar execute getId() and place its value instead?
My failed attempt.
Template:
'<h4>Order number: {{orderNumber}}</h4><h4>{{#getId }}</h4>'
Registered function:
hbs.registerHelper('getId', function(param, opts) {
//return param.getId()
return 666;
});
No matter what I try I always get this error:
"Parse error on line 1:\n...{{#getId }}\n-----------------------^\nExpecting 'OPEN_INVERSE_CHAIN', 'INVERSE', 'OPEN_ENDBLOCK', got 'EOF'"
If I remove getId from the template, then it works as expected.

First you need to create new Handlebars helper:
Handlebars.registerHelper('getId', function(param, opts) {
return 1;
});
Then you can call it using:
<span>{{getId someParam}}</span>

Related

TypeError: undefined is not an object when unit testing with jasmine

I'm trying to write a unit test for a function and I'm getting an error. I'm also unsure how to test other parts of the function correctly.
private dictionaryMap (loggedIn, response) {
const translations = this.convertToArrays(response.data.translations);
this.configureMomentLocale(language);
if (!loggedIn) {
this.cachePublicDictionary(translations);
}
// not testing this part
this.dictionary = new Dictionary({
translationMap: Object.assign({}, this.getPublicDictionaryFromCache() || {}, translations),
});
return this.rx.Observable.of(this.dictionary);
}
And my unit test so far looks like this:
describe('dictionaryMap', () => {
it('calls configureMomentLocale()', () => {
const foo = {
'foo':'bar',
};
spyOn(service, 'configureMomentLocale');
service.dictionaryMap({}, false);
expect(service.configureMomentLocale).toHaveBeenCalled();
});
});
And when I run this test I get this error:
TypeError: undefined is not an object (evaluating 'response.data.translationMap')
Do I need to mock response.data.translations or assign the json structure? (translationMap: {'email': 'email', 'forgotPassword': 'Forgot password?'})
Also, I'm not sure how to properly test the other parts of the function, like the if statement or returning the observable. I am new to unit testing.
Your method dictionaryMap accepts 2 parameters - 1st is loggedIn (presumably boolean) and the 2nd one is response. On the first line of that method (before calling configureMomentLocale) you have a line const translations = this.convertToArrays(response.data.translations); which expects the response variable to have a property named data.
In your test, you have 2 errors on the line service.dictionaryMap({}, false);:
You're setting the arguments in reverse order - you should put the boolean argument first and the object one second
The object doesn't have a property named data
The line should be corrected to be something similar to service.dictionaryMap(false, { data: {} });. You might even need to define translations property for data object - it really depends on what this.convertToArrays function does and how it handles undefined values.

The service call is returning the function definition than the actual return in angular

Here in summary.controller.js at line 37 i'm calling the 'filter.jdpa' which is the method defined in the service: filter.js.
The method is meant to return an array jdpaarr but when i call it in the controller i get the whole method definition as the output
The code for the service is also attached below
(function () {
'use strict';
angular.module('app')
.service('filter', filter);
function filter() {
this.jdpaf=jdpaf;
this.yearf=yearf;
this.cityf=cityf;
function jdpaf(){
var jdpaarr=['All','JDPA','Non-JDPA'];
console.log(jdpaarr);
return 'jdpaarr';
}
function yearf(){
var yeararr=['2011','2012','2013','2014'];
console.log(yeararr);
return 'yeararr';
}
function cityf(){
var cityarr=['Delhi','Mumbai','Trivandrum','Banglore','Hyderabad'];
return cityarr;
}
}
})();
I have given console.logs in the service itself but that fails to work.
But why is the whole function definition being shown in the function call ?
You are basically assigning the definition only.
Try calling/executing it on initialization and saving the returned value in your scope like.
$scope.Filterarray.jdpa = filter.jdpaf();
Hope this helps.

angularJS global filter module

I am having trouble getting my custom filter to work.
I have a module of global filters:
angular.module('globalFilters', []).filter('dateRange', function () {
return function(item) {
console.log(item);
return true;
}
});
This is injected into my app on creation.
I am trying to apply this to an ng-repeat:
tr.pointer(ng-repeat="asset in completed | dateRange", ng-animate="'animate'", ng-click="selectAsset(asset);")
td {{asset.Name}}
However adding this filter will filter all assets out of table. To try to isolate the problem I am returning true for the function to display all assets but it is not working.
Upon logging item to the console, result appears to be an array of all assets so I guess something is wrong.
I was following this tutorial https://docs.angularjs.org/tutorial/step_09
Thanks!
You are filtering an array...so your filter function needs to return an array.
.filter('dateRange', function () {
return function(itemArray) {
if(!itemArray){
return null
}else{
return itemArray.filter(function(item){
// conditions of filter
});
}
}
});
When you define a custom filter function, the value passed into the filter is replaced by the value returned from the filter, so you are replacing item with true.
For a filter which logs the input without changing it, just return the input:
return function(item) {
console.log(item);
return item;
}

how to assign function to marionette.template

As per I know, marionette.template accept either jquery selector or compiled template string.
If I write code like in the following way, working fine
exports.ProductInfoView=Backbone.Marionette.ItemView.extend({
domInfo:{
mainTemplateId:"tagProductListTpl",
tableTemplateId:"taginfoViewTpl"
},
template:commomFunctions.templateCompilation("tagProductListTpl",""),
onRender:function(){
this.templatingProductInformation();
},
modelEvents:{
"change:currentJson":"templatingProductInformation"
},
templatingProductInformation:function(){
console.log(this.el);
//this.el.innerHTML=commomFunctions.templateCompilation(this.ui.mainTemplateId,"");
}
});
Note :commonFunctions.templateCompilation() accept templateId as first argument and data as second argument. It will compile handlebars template and it return compiled template.
If I assign that return value to template, working fine.
I want to make data for templating,so I am passing function to template like in the following way.
exports.ProductInfoView=Backbone.Marionette.ItemView.extend({
domInfo:{
mainTemplateId:"tagProductListTpl",
tableTemplateId:"taginfoViewTpl"
},
template:function(){
return commomFunctions.templateCompilation("tagProductListTpl","");
},
onRender:function(){
this.templatingProductInformation();
},
modelEvents:{
"change:currentJson":"templatingProductInformation"
},
templatingProductInformation:function(){
console.log(this.el);
//this.el.innerHTML=commomFunctions.templateCompilation(this.ui.mainTemplateId,"");
}
});
This way also working fine, If you observer I hard coded templateId("tagProductListTpl") inside function.But I don't want like that. I want to use like this.domInfo.mainTemplateId instead of hard coding. that way it's not working fine.
It's throwing error. I know it's out of scope. but how can I achive this.
can anyone help me.
Thanks.
I will advise you to rewrite Marionette.TemplateCache.prototype.compileTemplate which is responsible for template compilation. Look at this post, there almost the same issue.
Marionette.TemplateCache.prototype.compileTemplate = function (yourRawTemplate) {
// In case if template is function
if (_.isFunction(yourRawTemplate)) {
return yourRawTemplate;
} else {
return Handlebars.compile(yourRawTemplate);
}
};
And if you loading template files from remote server you also need to rewrite Backbone.Marionette.TemplateCache.prototype.loadTemplate. Here example:
Marionette.TemplateCache.prototype.loadTemplate = function ( templateId ) {
var template = '',
templateUrl = 'path_to_your_template/' + templateId + '.html';
// Loading template synchronously.
Backbone.$.ajax( {
async : false,
url : templateUrl,
success : function ( templateHtml ) {
template = templateHtml;
}
} );
return template;
};

TypeError when using Jquery and Object property function

I'm getting an error when using jquery and I would like to know its cause:
here is part of my code
function Wbook(name){
this.name = name;
}
Wbook.prototype.GetHTML = function() {
Object.defineProperty(this, "GetHTML", {enumerable : false,
configurable : true});
var html ='<h1>TEST1</h1>';
return html;
};
var rs = {};
rs.WB = new Wbook('test1');
var foo = rs.WB.GetHTML();
$(foo).appendTo('div#id1'); // This works
$(rs.WB.GetHTML()).appendTo('div#id1');
// This doesn't work >> TypeError: rs.WB.GetHTML is not a function
I can also getting to work if I comment the Object.defineProperty section, so I'm suspecting this might have to do with the enumerability, but I'm not sure of it
//Edit: While creating Jfiddle, I notice rs.WB.GetHTML() is always failing the second time it runs :-/. (It works fine if I comment the Object.defineProperty section)
The first time you call .GetHTML() it's returning some HTML, but in the process the Object.defineProperty call is overwriting the .GetHTML method with a new property that has no value.
It's therefore unsurprising that on the second invocation you get an error because the value of .GetHTML by then is undefined.
If the intent of your code is to ensure that GetHTML is not enumerable, use the following code which directly adds the method to Wbook.prototype and (automatically) sets it non-enumerable:
Object.defineProperty(Wbook.prototype, 'GetHTML', {
value: function() {
...
}
});

Categories