Combining strings to a bound variable in Ember.js - javascript

I need to include images in my Ember.js/Handlebars template.
I was using <img {{bindAttr src="short_name"}}> which would work if the image was exactly the value of short_name and in the root directory.
However, I need to construct the img src like this:
'/images/avatars' + short_name + '_avatar.jpg'
How would this be accomplished in ember/handlebars?

Considering that short_name doesn't change, you could do it like this:
<img src="/images/avatars{{unbound short_name}}_avatar.jpg">
But if short_name change a lot, you should use a computed property like so:
var SomeModel = Ember.Object.extend({
shortName: null,
imgSrc: function() {
var shortName = this.get('shortName');
return '/images/avatars' + shortName + '_avatar.jpg';
}.property('shortName')
});
And then on your template:
<img {{bindAttr src="imgSrc"}}>

Related

ReactJS Dynamic Anchor tag href rendering based on csv file Undefined

I'm using React and React-DOM inline to make a dynamic filter gallery for showcasing projects of my contributors.I have parsed a CSV file that contains the names of the different contributors, the category based on which the tiles will be sorted (project categories) and the URL to each project this is stored in data variable.
for(var i=0;i<data.length;i++) {
var photo = {
id: i,
category: data[i].Style,
pageurl: "./explore/" + data[i].name.toLowerCase().replace(/ /g, "-") + ".html" ,
//iu: "./explore/" + String(data[i].name) ,
imageUrl: "./explore/" + String(data[i].image_path)
};
PHOTODATA.push(photo);
}
When I log this PHOTODATA variable the DOM shows the different URLs correctly as expected, like this.
0: {id: 0, category: "Futurism", pageurl: "./explore/steely-dan.html", imageUrl: "./explore/thumbnail.jpg"}
This is the piece of code where I render the div and the <a> tag using React
var Photo = React.createClass({
render: function(){
return (
<a className = "photo-container" href= {"./explore/"+ String(this.props.pageurl)} >
<div data-category={this.props.category} >
<img src={this.props.imageUrl} />
</div>
</a>
);
}
And this is how the rendered tag looks in the DOM.
<a class="photo-container" href="./explore/undefined.html" data-reactid=".0.1.$0"><div data-category="Futurism" data-reactid=".0.1.$0.0"><img src="./explore/thumbnail.jpg" data-reactid=".0.1.$0.0.0"></div></a>
I'm puzzled by how the URL comes out as undefined while when I try something like {"https://www.google.com"} then it renders it correctly. Only the dynamic rendering seems to have a problem. I've also tried changing the names of the variables but the issue still persists. Either the DOM doesn't render the href of it renders it as undefined.
How can I fix this issue to link each divs to their own custom html page defined by the CSV file?

How to pass a props value to a JS function from Vue component

I have a JS file with a function and component as below:
function emojify(name){
var emj='';
if (name!=''){
emj= '<img src="/static/emojis/'+name+'.png" alt="img" > '
}
return emj
}
Vue.component("cmp2",{ props:["name"] , template: `<p>` + emojify("name") + `</p>`})
I call that component from HTML as below
<cmp2 name="ron" ></cmp2>
Image of ron doesnt show up. But if i declare my component as below it works:
Vue.component("cmp2",{ template:'<p>' + emojify("ron") + '</p>'})
So the image ron exists and works fine. I am just unable to pass value of props name to the function emojify.
How can that be done?
You cannot do this as the template is computed at compilation time but props are evaluated at run / render time.
What you can do is bind the src attribute, eg
<p>
<img v-if="name" :src="`/static/emojis/${name}.png`" alt="img">
</p>

Backbone view, needs to render an image in the template depending on params

So I have a view that is going to render a template that will include an image. This image is dependent on the variable being passed in, located in assets/images.
Basically, how can I pass in this model into the template so it can render the correct image?
Normally in Rails I would just do in a Rails ERB Template:
<img class="item-portrait"
src="<%= image_path("items/" + item.name.gsub(" ", "-").downcase + ".png")
%>">
How can I accomplish the same effect in a JST template?
Let's assume your model looks like this :
var itemPortraitModel = new Backbone.Model({
'path' : 'path_to_file'
});
and your view is similar to this :
var ItemPortraitView = Backbone.View.extend({
template: JST['itemPortraitTemplate'],
render: function() {
this.$el.html(this.template(this.model.attributes));
return this;
}
});
then in your itemPortraitTemplate template code, any of the properties in your model will be available:
<img class="item-portrait"
src="<% print(("items/" + path + ".png") %>">

Create HTML tag from Javascript object

What is the best method to change this object
{
src: 'img.jpg',
title: 'foo'
}
into a valid HTML tag string like this
<img src="img.jpg" title="foo" />
Solution 1
With jQuery this is easy; but complicated:
$('<img/>').attr(obj).wrap('<div/>').parent().html();
Any better ideas?
Why not:
$('<img/>', obj).get(0).outerHTML;
Fiddle
You do not need to wrap it in a div using multiple functions and get the html, just use get(0) to get the DOM element and outerHTML to get the element's html representation.
Unless you are using browsers really old you can rely on outerHTML
Here is a JSPerf to compare the performance diff between the approaches.
Perhaps slightly more concise than PSL's?
$('<img />',object)[0].outerHTML;
Simple with jquery
$("<div>").append($('<img />',object)).html();
If you are only doing one element, then this solution is overkill, but I thought I would post it anyway as I don't know what your project is.
Have you considered a JavaScript template engine? I've been playing around with Swig lately, as it is quite lightweight, but there are many options. Basically, you create a template, pass a JavaScript object, and the compiled template is executed, returning a string of HTML.
Example from Swig Documentation
Template
<h1>{{ pagename|title }}</h1>
<ul>
{% for author in authors %}
<li{% if loop.first%} class="first"{% endif %}>
{{ author }}
</li>
{% else %}
<li>There are no authors.</li>
{% endfor %}
</ul>
JavaScript to Render Template
var template = require('swig');
var tmpl = template.compileFile('/path/to/template.html');
tmpl.render({ // The return value of this function is your output HTML
pagename: 'awesome people',
authors: ['Paul', 'Jim', 'Jane']
});
Output
<h1>Awesome People</h1>
<ul>
<li class="first">Paul</li>
<li>Jim</li>
<li>Jane</li>
</ul>
Making html elements based out of objects containing attribute-attribute values such as
{
src: 'img.jpg',
title: 'foo'
}
almost completely falls into the paradigm of cook.js.
The command which you would issue with cook would be:
img ({
src: 'img.jpg',
title: 'foo'
})
If the attribute details are stored as given in your example,
in a variable obj then:
img(obj)
For more details check it out at cook.relfor.co.
Here's how you make it as a string:
var img = '<img ',
obj = { src : 'img.jpg', title: 'foo' };
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
img += prop + '=' + '"' + obj[prop] + '" ';
}
}
img += '/>';
http://jsfiddle.net/5dx6e/
EDIT: Note that the code answers the precise question. Of course it's unsafe to create HTML this way. But that's not what the question asked. If security was OP's concern, obviously he/she would use document.createElement('img') instead of a string.
EDIT 2: For the sake of completeness, here is a much safer way of creating HTML from the object:
var img = document.createElement('img'),
obj = { src : 'img.jpg', title: 'foo' };
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
img.setAttribute(prop, obj[prop]);
}
}
http://jsfiddle.net/8yn6Y/

Ember.js property and ArrayController in template

I've got a setup like this in Ember:
App.ListObject = Ember.Object.create({
knownThings: function() {
var ot = this.openThings.get('content');
var ct = this.closedThings.get('content');
var kt = ot.concat(ct);
var known = Ember.ArrayController.create({content: kt});
return known;
}.property(),
openThings: Ember.ArrayController.create({
content: []
}),
closedThings: Ember.ArrayController.create({
content: []
}),
})
Basically, known things is the combined arrays of openThings and closedThings. I can't seem to figure out how to iterate over knownThings in the template. Just doing
{{#each App.ListObject.knownThings }}
Does not work as the property needs to be accessed like App.ListObject.get('knownThings') but that doesn't work in the template unless I'm doing something terribly wrong. Iterating over the other attributes in the template does work (open and closed things)
So, how would you iterate over knownThings in the template?
Slight Modifications needed...
Firstly,
knownThings: function() {
//use get to retrieve properties in ember, Always !
var ot = this.get('openThings').get('content');
//var ot = this.get('openThings.content') if you are using latest ember
var ct = this.get('closedThings').get('content');
//var ot = this.get('closedThings.content') if you are using latest ember
var kt = ot.concat(ct);
var known = Ember.ArrayController.create({content: kt});
return known;
//Add dependencies to keep your knownThings in sync with openThings & closedThings if at all they change in future
}.property('openThings', 'closedThings')
Coming to Handlebars iterate using
//you forgot content property, and in handlebars you don;t need to use get, dot operator is enough
{{#each App.List.knownThings}}
Let me know if this works...
Update
Working Fiddle...
Unless I didn't understand what you're saying, I think you should have ListObject extending Em.ArrayController instead of Em.Object. Also, if your property depends on content, it should be .property('content.#each'). If you're using the router, your template should look like {{#each thing in controller.knownThings}} and you use {{thin.something}}, if not using router, then {{#each item in App.listObject.knownThings}}. Also, openThings and closedThings don't seem to be correct and the way you're accessing them is wrong too.
I didn't write a fiddle for this specific case cause I don't really know what you're trying to do, but take a look at this fiddle, specifically at App.ResourcesController and the template 'resources-view':
Controller:
// ...
App.ResourcesController = Em.ArrayController.extend({
content: [],
categories: ['All', 'Handlebars', 'Ember', 'Ember Data', 'Bootstrap', 'Other'],
categorySelected: 'All',
filtered: function() {
if(this.get('categorySelected') == "All") {
return this.get('content');
} else {
return this.get("content")
.filterProperty(
"category",
this.get('categorySelected')
);
}
}.property('content.#each', 'categorySelected'),
filteredCount: function() {
return this.get('filtered').length;
}.property('content.#each', 'categorySelected'),
hasItems: function() {
return this.get('filtered').length > 0;
}.property('filteredCount')
);
// ...
Template:
<script type="text/x-handlebars" data-template-name="resources-view">
<h1>Ember Resources</h1>
{{#view Bootstrap.Well}}
The following is a list of links to Articles, Blogs, Examples and other types of resources about Ember.js and its eco-system.
{{/view }}
{{view Bootstrap.Pills contentBinding="controller.controllers.resourcesController.categories" selectionBinding="controller.controllers.resourcesController.categorySelected"}}
<i>{{controller.filteredCount}} Item(s) Found</i>
{{#if controller.hasItems}}
<ul>
{{#each resource in controller.filtered}}
<li>
<a {{bindAttr href="resource.url"
target="resource.target"
title="resource.description"}}>
{{resource.htmlText}}
</a>
</li>
{{/each}}
</ul>
{{else}}
{{#view Bootstrap.AlertMessage type="warning"}}
Couldn't find items for {{controller.categorySelected}}
{{/view}}
{{/if}}
</script>

Categories