Writing helper : What's the use of the end arguments - javascript

Apologies for the name of the question, you will quickly understand what I mean.
On Ember website, if you follow the example given you will get the following :
Ember.Handlebars.helper('fullName', function(person) {
return person.get('firstName') + ' ' + person.get('lastName');
}, 'firstName', 'lastName');
But if you take out the end of the function it's still working :
Ember.Handlebars.helper('fullName', function(person) {
return person.get('firstName') + ' ' + person.get('lastName');
});
Is there any advantage, disadvantage to add/remove these values.

The first aproach have dependent keys, so if firstName or lastName is changed, the template is updated. The second just observe the person instance, not your properties.
Give a look in that fiddle for further understanding

These values indicate the properties to which this helper is bound to. This means that if the values of these properties change the helper will be updated.
The following example demonstrates this ,
http://emberjs.jsbin.com/udOkupe/1
By pressing the test button the firstName value is changed, only one of the fullName helpers will be updated.
hb
<script type="text/x-handlebars">
<h2>Welcome to Ember.js</h2>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{firstName}}<br/>
{{lastName}}
<br/>
{{fullName this.model}}<br/>
{{fullName2 this.model}}<br/>
<button {{action "test"}}>test</button>
</script>
js
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.IndexRoute = Ember.Route.extend({
test:null,
model: function() {
this.set("test",App.Person.create({firstName:"my fname",lastName:"my lastname"}));
return this.get("test");
}
,
actions:{
test:function(){
this.get("test").set("firstName","lallalal");
}
}
});
Ember.Handlebars.helper('fullName', function(person) {
return "fullName:"+person.get('firstName') + ' ' + person.get('lastName');
}, 'firstName', 'lastName');
Ember.Handlebars.helper('fullName2', function(person) {
return "fullName:"+person.get('firstName') + ' ' + person.get('lastName');
});
App.Person = Ember.Object.extend({
firstName:"",
lastName:""
});

Related

Trouble outputting model data dynamically with jQuery

I am trying to create some divs out of my view model using jQuery. This is the code:
<script src="~/Scripts/jquery-3.1.1.min.js"></script>
<script>
$(document).ready(function () {
var model = #Html.Raw(Json.Encode(Model.MemberProfiles));
console.log(model);
for (profile in model) {
$("#viewMembers").append("<div class='profilePreview'><p>" + profile["FirstName"] + "</p></div>");
}
$("#viewMembersBtn").click(function () {
$("#viewMembers").toggle();
});
});
As you can see here, the "FirstName" property evaluates to undefined. If you look at the console.log() in this same image, the objects have the correct data. How do I retrieve the FirstName property correctly?
You need model[profile].FirstName:
for (var profile in model) {
$("#viewMembers").append("<div class='profilePreview'><p>" + model[profile].FirstName + "</p></div>");
}
Try to access your JavaScript Model like this:
for (profile in model) {
$("#viewMembers").append("<div class='profilePreview'><p>" + profile.FirstName + "</p></div>");
}

Clicking old list only shows last created id, should show the list-id im clicking

I have a dashboard where I can create lists and have them printed out on the dash, but when I click on either one of them it only opens up the one last created. What am I doing wrong? I am using the latest Angular, Firebase and AngularFire.
My code looks something like this, with create and open functions:
allLists = new Firebase('https://url.firebaseio.com/lists/' + authData.uid);
// Modal service for creating a new list
$scope.createList = function(){
newList = allLists.push({
name: 'new list'
});
listUID = newList.key();
$rootScope.listUID = new Firebase('https://url.firebaseio.com/lists/' + authData.uid + '/' + listUID);
// Runs the ngDialog scheme with template etc
ngDialog.open({
template:'user-modal.html',
controller: 'createController',
scope: $scope,
className:'ngdialog-theme-default'
});
console.log('listUID is: ' + listUID);
return listUID;
};
// Modal service for opening an old list for edit/remove/whatnot
$scope.openList = function(index){
oldUID = new Firebase('https://url.firebaseio.com/lists/' + authData.uid + '/' + listUID);
ngDialog.open({
template: 'user-old-list.html',
controller: 'oldListController',
className: 'ngdialog-theme-default',
scope: $scope
});
console.log(listUID);
};
With simple HTML as this:
<div ng-repeat="(id, lists) in listCounter" class="user-lists">
<button ng-click="openList()" ng-model="listCounter[id]">{{lists.$id}}<br />{{lists.name}}</button>
</div>
Which refers to:
$rootScope.listCounter = $firebaseArray(allLists);
You are not passing id to openList(). try ng-click="openList(id)" in the template. also you are not refering to index anywhere in your function.

Nothing handled the event error in Emberjs

I am trying to filter a JSON response by using 'filterProperty' in Emberjs. But I am getting this error, Uncaught Error: Nothing handled the event 'last'
Here's my App.js
App = Ember.Application.create({});
App.IndexRoute = Ember.Route.extend({
renderTemplate : function(controller) {
this.render('MyApp', {
controller : controller
});
},
model : function() {
return App.MyTemplateModel.find();
}
});
App.IndexController = Ember.ArrayController.extend({
last : (function() {
this.get('content').filterProperty('last_name', 'Solow');
}).property('content.#each.type')
});
App.MyTemplateModel = Ember.Model.extend({
id : Ember.attr(),
last_name : Ember.attr(),
first_name : Ember.attr(),
suffix : Ember.attr(),
expiration : Ember.attr()
});
App.SiteController = Ember.ObjectController.extend({
});
App.MyTemplateModel.url = "http://ankur1.local/index.php/api/example/users/";
App.MyTemplateModel.adapter = Ember.RESTAdapter.create();
var existing = App.MyTemplateModel.find();
App.MyTemplateModel.camelizeKeys = true;
Here's my HTML page,
<script type="text/x-handlebars" data-template-name="MyApp">
{{#each item in content }}
<tr><td>
{{id}} <p> {{item.first_name}} {{item.expiration}}</p>
</td></tr>
{{/each}}
<button {{action last}}>filter</button>
</script>
<script type="text/x-handlebars">
<h1>Application Template</h1>
{{outlet}}
</script>
</body>
What I might be doing wrong in my App.js or should I use any other property to filter the JSON response?
You declared the property last on your IndexController as Computed Property, but if you want to use the {{action}} helper, this is not allowed. It has be a plain function. This is why Ember does not find a suitable event anywhere and complains about it.
App.IndexController = Ember.ArrayController.extend({
// for initial filling of this property, will be overridden by last action
filteredContent : Ember.computed.oneWay("content"),
last : function() {
var filtered = this.get('content').filterProperty('last_name', 'Solow');
this.set("filteredContent", filtered);
}
});
<script type="text/x-handlebars" data-template-name="MyApp">
{{#each item in filteredContent }}
<tr><td>
{{id}} <p> {{item.first_name}} {{item.expiration}}</p>
</td></tr>
{{/each}}
<button {{action last}}>filter</button>
</script>
So i did basically two things:
I changed the computed property to a plain function.
The template is iterating over filteredContent instead of content. (Note the initialization i had to do on your Controller.)
Sou the basic mechanism is to have an additional property on your Controller, which holds the filtered content. You have to expand on this, because your usecase is a bit more complex for sure. :-)

this in event handling functions of Meteor: How does this get bound to model object?

The following code is taken from a tutorial in tutsplus.
if (Meteor.isClient) {
var Products = new Array(
{ Name: "Screw Driver",
Price: "1.50",
InStock: true},
{ Name: "Hammer",
Price: "2.50",
InStock: false}
);
Template.Products.ProductArr = function () {
return Products;
};
Template.Products.events = {
"click .Product": function () {
if (this.InStock)
confirm("Would you like to buy a " + this.Name + " for " + this.Price + "$");
else
alert("That item is not in stock");
}
};
}
Here is the template:
<template name="Products">
{{#each ProductArr}}
<div class="Product">
<h2>{{Name}}</h2>
<p>Price: ${{Price}}</p>
{{#if this.InStock}}
<p>This is in stock</p>
{{else}}
<p>This is sold out</p>
{{/if}}
</div>
{{/each}}
</template>
I wonder how this get bound to the model object product? This looks like magic to me.
The expression "click .Product" specifies that the click event on HTML elements having class Product should trigger the specified function. I understand it. But I don't understand why this is bound to an element of the Products array.
This is how Handlebars (which Meteor builds on) works. What you're seeing in the template isn't pure JS, but syntax specific to Handlebars.
Inside the each block helper, the context is to set each element of the array you're iterating over. So if you use InStock, it will look for it on the element of the current iteration.
The this keyword is used for disambiguation. This comes in handy if you have a general helper registered with the name InStock, like this, for example:
Template.Products.InStock = function (){
//...
};
But you want to make sure you're referring to the property of the element from the array, so you can use this to access its context explicitly.

How can I include a Javascript string constructor in a JSON string?

I'm building a template to Jquery Mobile listviews. To make the template fully generic, I need to pass the listitem text. So currently my listview config looks like this:
<ul data-role="listview" data-create="false" class="template" data-config='{
"type":"listview",
"data":"getRetailers",
"custom_classes":["embedded_filter updateResults f-875","nMT pickList f-875 widget_listview","f-n",""],
"lib":"static_listview.html",
"tmp":"tmp_listview_inset",
"lang":"locale_search",
...
}'></ul>
My problem is how to include a Javascript constuctor for the list item text. This should be the following:
inv.company+', '+ inv.zip + ', ' + inv.city
But inserting it like this:
...
"text":"inv.company+', '+ inv.zip + ', ' + inv.city"
}
does not work.
Question:
How to include Javascript constructors in JSON?
Try this code:
"text":"'"+ inv.company+ "', '"+ inv.zip + "','" + inv.city+ "'";
Ok. Not nice, but working:
1) In my JSON I'm only passing a function name like so:
<ul data-role="listview" data-create="false" class="template" data-config='{
"type":"listview",
"data":"getRetailers",
"custom_classes":["embedded_filter updateResults f-875","nMT pickList f-875 widget_listview","f-n",""],
"lib":"static_listview.html",
"tmp":"tmp_listview_inset",
"lang":"locale_search",
"text":"buildRetailers",
...
}'></ul>
2) Then in my script I'm adding buildRetailers to my dynoData module:
var dynoData = {
...
buildRetailers: function (inv) {
return inv.company+', '+ inv.zip + ', '+ inv.city;
},
...
}
3) And call this from my listview string builder:
....
listItem = listItem.replace( widget.options.re_theme, li_theme );
listItem = listItem.replace( widget.options.re_iconpos, li_iconpos );
listItem = listItem.replace( widget.options.re_icon, li_icon );
// call the function to return the list item text
listItem = listItem.replace( widget.options.re_text, dynoData[ li_text ](inv) );
So I can't seem to pass the function string in the JSON configuration so I need to add a function to construct what I need. If someone knows a better way please post. I will test and check.
Can't you just pass what the object literal version of the inv object is.
"text" : {
"company": "some value here",
"zip": "another value here",
"city": "another value"
}
Normally you would do it like this:
"text": function(){ return inv.company+', '+ inv.zip + ', ' + inv.city }
But I'm not sure if it ever works. You can try it anyways.

Categories

Resources