AngularJS custom directive does not work with in Handlebars template - angularjs

This is the code that works:
<select-city country="US"></select-city>
This is the code that not works:
<select-city country="\{{country}}"></select-city>
For testing, I made this:
\{{country}}
It correctly prints US.
Note: I have to use \ because I use Handlebars template.

You need to change this line:
<select-city country="\{{country}}"></select-city>
To the following:
<select-city country="'\' + {{country}}"></select-city>
If you need to do this several times, it may be interesting to write a custom getter in order to avoid doing this in the view:
$scope.getCountry = function() {
return '\\' + $scope.country;
}
In the view:
<select-city country="{{getCountry()}}"></select-city>

Related

Angular $compile misbehaving when returning value

I'm trying to use Angular $compile to compile my template.
My template looks like this:
var template = '<div>{{obj.someValue}}</div>';
I'm showing my data in another ctrl/view:
$scope.obj.someValue = "hi";
$scope._html = '';
<div>{{html}}</div>
Now at some point I render my template.
$compile(template)($scope);
$scope._html = template;
At this point I'm confused. Because template hasn't changed.
So I tried the following:
$scope._html = $compile(template($scope);
This does work and compile the template correctly, but my entire console is flooded with errors:
TypeError: Illegal invocation
at Sa (angular.js:265)
at r (angular.js:319)
What am I doing wrong exactly?

Testing events and document content in karma-jasmine unit-testing

I want to test the following functions using jasmine-karma unit testing but I can't find a way to do so.
function One:
$scope.info = function(text){
$(":root").find("#info").remove();
var htmlObject = "<div id='info' info-alert text='"+$sanitize(text)+"'/>";
var comments = $compile( htmlObject )( $scope );
$(document.body).append( comments );
};
function 2:
$scope.$on('settingsChanged',function(){
$scope.getSettings();
});
I have tried reading the documentation on how to test events and play with the tests but nothing seems to work.
This is my last attempt for the first but the last line is not the right way of doing it I suppose:
it('info', function() {
var text="Some information";
var controller=createController();
scope.info(text);
expect($(document.body).val()).toContain(text);
});
I tried for the second one something similar but nothing seems to work
Your text might have been altered by $sanitize(text)
AngularJS official documentation states that:
- $sanitizeProvider
- service in module ngSanitize
Sanitizes an html string by stripping all potentially dangerous tokens.
So please check if document.body contains your text, and that it has not been altered by $sanitize(text)

AngularJs - QueryString value & ng-include

I am trying to capture the querystring and apply the value to my ng-include.
My querystring: http://mydomain.com/?target=W7ROP175T5TEHW2
My MainCtrl: $scope.target = $location.search()['target'];
$scope.target is picking up the value.
Doing a simple text write, ie {{target}} works.
This does not work: <div ng-include="'/_UserSession/{{target}}/assets/menu.html'"></div>
Any ideas?
You need to escape the value, it is an expression.
ng-include="'/_UserSession/' + target + '/assets/menu.html'"
Also if you want to make sure that target is set before it attempts to include the template, you can add ng-if ="target". This way it will avoid a bad request.
OK, I solved it, I hope this helps others as well:
HTML
<ng-include src="session()"></ng-include>
Controller
$scope.target = $location.search()['target'];
$scope.session = function() {
return "/_UserSession/" + $scope.target + "/assets/menu.html";
};

Underscore, can't call replace of undefined

I've experienced this error before and tried the solutions I've found on SO for it, but I can't get around it in this case by trying the solutions I've found. I have a question_template that I placed in the header of my index file with the js script tags at the bottom of the file. In the initializer to the view, I get the template using jQuery html function, and the console log shows the template is retrieved from the index.html. However, when i try to insert it into underscore _.template, it's triggering the can't call replace of undefined error
var QuestionView = Backbone.View.extend({
el: $(".east"),
initialize: function(){
var template = $('#question_template').html();
console.log(template);
this.template = _.template(template); #error triggered
},
Since I'm able to log the template, I don't see what my problem is? This is part of the underscore code.
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
source += text.slice(index, offset)
.replace(escaper, function(match) { return '\\' + escapes[match]; });
First question: What would 'text' represent, which, in my case, is undefined? I would have thought that 'text' is the template, but since I can log my template how is it undefined?
I also have all of the js code (including the initialization of the Question view) wrapped in the document ready, which in other SO questions on this issue was the solution
$(function() {
...code ommitted...
var question_view = new QuestionView({ model: game});
});
Second question: is there anything else I can try
Update
Note, I subsequently pass the model data to the template but it never gets that far because the error is triggered
**$(this.el).html(this.template(response));**
I prepare the templates in three steps
1. var template = $('#question_template').html();
console.log(template);
2. this.template = _.template(template);
3. $(this.el).html(this.template(response));
You should pass the model data to the template,
this.template = _.template(template, this.model.toJSON());

How to use Backbone.Marionette.ItemView with Mustache

The following code works fine using Backbone.Marionette.ItemView but not Mustache.
Backbone.Marionette.ItemView - no Mustache
I would like to use the same code but loading the template varaible using Mustache.
Here is my code:
Backbone.Marionette.ItemView - with Mustache
Any idea why my code does not work and why?
Thanks
I'd like to update the answer here a bit as I was just struggling with this, and I was using this answer as a reference.
Here are my findings:
The answer here is a bit out of date with the current version of Mustache (which is understandable as it's pretty old)
Mustache.to_html is now deprecated, but still exists as a simple wrapper around Mustache.render for backwards compat. Check out this link.
Additionally, I found overriding Marionette.Renderer.render, as in the accepted answer above, completely bypasses the Marionette.TemplateCache layer which may not be the desired behavior.
Here's the source for the Marionette.Renderer.render method:
render: function(template, data){
if (!template) {
var error = new Error("Cannot render the template since it's false, null or undefined.");
error.name = "TemplateNotFoundError";
throw error;
}
var templateFunc;
if (typeof template === "function"){
templateFunc = template;
} else {
templateFunc = Marionette.TemplateCache.get(template);
}
return templateFunc(data);
}
Source
As you can see it accesses the Marionette.TemplateCache.get method and the above answer does nothing to maintain that functionality.
Now to get to my solve (note: the above answer is not wrong necessarily; this is just my approach to maintain the Marionette.TemplateCache layer):
As the comments suggest above, override compileTemplate instead:
Marionette.TemplateCache.prototype.compileTemplate = function(rawTemplate) {
// Mustache.parse will not return anything useful (returns an array)
// The render function from Marionette.Renderer.render expects a function
// so instead pass a partial of Mustache.render
// with rawTemplate as the initial parameter.
// Additionally Mustache.compile no longer exists so we must use parse.
Mustache.parse(rawTemplate);
return _.partial(Mustache.render, rawTemplate);
};
Here's a working JSFiddle as proof.
In the fiddle, I've also overridden Marionette.TemplateCache.loadTemplate to demonstrate that it's only called once. The body of the function only adds some debug output and then re-implements most of the original functionality (minus error handling).
Marionette assumes the use of UnderscoreJS templates by default. Simply replacing the template configuration for a view isn't enough. You also need to replace how the rendering process works.
In your simple example, you only need to override the Marionette.Renderer.render function to call Mustache, and then set the template of your views to the string template that you want:
Backbone.Marionette.Renderer.render = function(template, data){
return Mustache.to_html(template, data);
}
var rowTemplate = '{{ username }}{{ fullname }}';
// A Grid Row
var GridRow = Backbone.Marionette.ItemView.extend({
template: rowTemplate,
tagName: "tr"
});
Note that your JSFiddle still won't work even when you put this code in place, because the GridView is still using a jQuery selector/string as the template attribute. You'll need to replace this with the same type of template function to return mustache.
http://jsfiddle.net/derickbailey/d7qDz/

Resources