Writing a helper that produces bound results? - ember.js

I have a date/time formatting helper but what it produces does not update when the underlying property changes. This is not a surprise, but does anyone know how to produce bindings in helpers?
I invoke the helper like this...
{{timestamp created_at}}
...and here is the helper itself:
Handlebars.registerHelper('timestamp', function(context, options) {
var formatter = options.hash['format'] ? options.hash['format'] : 'hh:mm a MM-DD-YYYY';
var original_date = Ember.getPath(this, context); // same as this.get(context) ?
var parsed_date = moment(original_date);
var formatted_date = parsed_date.format(formatter);
return new Handlebars.SafeString("<time datetime=" + original_date +">" + formatted_date + "</time>");
});

It is now possible to create bound Handlebars helpers using a public Ember API.
Handlebars.registerBoundHelper('timestamp', function(date, options) {
var formatter = options.hash['format'] ? options.hash['format'] : 'hh:mm a MM-DD-YYYY';
var parsed_date = moment(date);
var formatted_date = parsed_date.format(formatter);
return new Handlebars.SafeString("<time datetime=" + date +">" + formatted_date + "</time>");
});
The parameter passed to the helper will have already been resolved, and the helper will be called again whenever the path changes.

It is unfortunately more complex than I'd like to create a custom helper with bound content. Here's an example that Peter Wagenet wrote: https://gist.github.com/1563710
I'll be lobbying for this to become easier.

Not sure if this applies to this particular question, but I also created helpers in views and wanted the values to update when data in the Ember.js view changed. The way I solved this problem was to write an observer on the values I wanted changed and used jQuery to update the specific value.
For example (in Coffeescript):
...
attrObserver: Ember.observer(() ->
$("#attrId").text(this.get("attr"))
...

Related

Jaggeryjs : Ajax call GET method

Working on WSO2 UES application for a dashboard project, in this, need to call REST api using GET method with HEADER data. (var headers ={"Authorization",getSecureToken};)
http://jaggeryjs.org/documentation.jag?api=get not giving enough info
<%
var getSecureToken = session.get("wso2-token");
var headers ={"Authorization",getSecureToken};
var userListUrl = "https://00.000.00.00:09000/users/1.0.0/users/list";
var userListData = get(userListUrl,headers,"json");
log.info(userListData);
%>
Any help will be appreciated. :-)
Update:
GET method function :
function FnMakeRequestGETCall(URL, METHOD, BASICAUTH, CONTENTTYPE, ACCEPTTYPE, INPUTDATA){
var VarBasicAuthCode = session.get('wso2-token');
xhr = new XMLHttpRequest();
xhr.open(METHOD, URL);
xhr.setRequestHeader("Authorization" , VarBasicAuthCode);
xhr.setRequestHeader("Content-Type", CONTENTTYPE);
xhr.setRequestHeader("Accept", ACCEPTTYPE);
xhr.send();
var VarResponse = xhr.responseText;
return VarResponse;
}
var userListUrl = "https://99.999.99.999:9445/users/1.0.0/users/list";
var headers ={"Authorization",getSecureToken};
var usersList = FnMakeRequestGETCall(userListUrl,"GET","Basic RlN4S2RrZEpNN3VaYWhHN0NFcEtlaTZEa3RzYTpXbmUxd29seHp2UTNSQ2RZbXhUUTJ2WkJTd0Fh","application/x-www-form-urlencoded; charset=UTF-8","application/json; charset=utf-8","");
log.info(usersList);
I think you can use the get() instead of creating a new XMLHttpRequest().
I think the problem of your get() is that it is asynchronous. So the usrsList variable doesn't get any value assigned right away. So what you basically have to do is use the get() and pass a success function.
General get() usage is as below.
get(url[, data][, headers][, data-type][, success(data, xhr)])
In your case get() should look as below.
get(userListUrl,null,headers,'text',function(usersList,xhr){
log.info(usersList);
});
If you used the XMLHttpRequest() because of the multiple header adding ability you can do the same with get. what you have to do is add those to your headers object.
var headers ={
"Authorization":VarBasicAuthCode,
"Content-Type" : CONTENTTYPE,
"Accept" : ACCEPTTYPE
};
please buzz me if this didn't work out.
(Note: I think you added your IP address with the question update ... :D)

How can I include given Handlebars helpers in Ember

On Github, many Handlebars helpers are presented. You can find them here.
I'd like to use them, but have no Idea, how to include them. The code is looking as it's javascript (files are ending with .js ...), but words like 'import','export','default' are confusing me.
As I understand (guess), I have to include the if-condition.js at first. Later, the other (included) files refer to this file.
But when I do this, the console throws an Error:
Uncaught SyntaxError: Unexpected reserved word .
Has anyone an idea, how to get these codes working?
import and export are keywords for the upcoming module syntax in the next version of Javascript. You can use them today by using a transpiler to convert it to normal ES5 syntax.
However, if you're only using a few helpers, it's very easy to 'transpile' them by hand. Instead of exporting the function, just pass it to a Ember.Hanldebars.registerBoundHelper call. Here's the if-condition helper:
Ember.Handlebars.registerBoundHelper('if-condition', function() {
var args = [].slice.call(arguments);
var options = args.pop();
var context = (options.contexts && options.contexts[0]) || this;
if (!options.conditional) {
throw new Error("A conditional callback must be specified when using the if-condition helper");
}
// Gather all bound property names to pass in order to observe them
var properties = options.types.reduce(function(results, type, index) {
if (type === 'ID') {
results.push(args[index]);
}
return results;
}, []);
// Resolve actual values for all params to pass to the conditional callback
var normalizer = function() {
return Ember.Handlebars.resolveParams(context, args, options);
};
// This effectively makes the helper a bound helper
// NOTE: 'content' path is used so that multiple properties can be bound to using the `childProperties` argument,
// however this means that it can only be used with a controller that proxies values to the 'content' property
return Ember.Handlebars.bind.call(context, 'content', options, true, options.conditional, normalizer, properties);
});

How to get store name of Ember Data model

How can I determine the "store name" (not sure what the proper terminology is) for a given ED Model? Say I have App.Payment, is there a store method that let's me look up its corresponding name, i.e. payment (for example to use in find queries)?
For Ember Data 1.0 (and later)
modelName is a dasherized string. It stored as a class property, so if you have an instance of a model:
var model = SuperUser.create();
console.log(model.constructor.modelName); // 'super-user'
For Ember Data Pre 1.0
typeKey is the string name of the model. It gets stored as a class property of the model, so if you have an instance of a model:
var model = App.Name.create({});
console.log(model.constructor.typeKey); // 'name'
You might be looking for Ember's string dasherize method:
var fullClassName = "App.SomeKindOfPayment";
var className = fullClassName.replace(/.*\./, ""); // => "SomeKindOfPayment"
var dasherizedName = Ember.String.dasherize(className); // "some-kind-of-payment"
There might be a built-in way to do this in Ember, but I haven't found it after spending some time looking.
EDIT: Ember Data might also let you get away with passing "App.SomeKindOfPayment" when a model name is needed - it usually checks the format of the model name and updates it to the required format by itself.
store.find, store.createRecord, and other persistence methods, use the store.modelFor('myModel'). After some setup it call container.lookupFactory('model:' + key); where key is the 'myModel'. So any valid factory lookup syntax is applicable. For example:
Given a model called OrderItems you can use: order.items, order_items, order-items, orderItems.
It turns out there was no need to do this after all, and here's why:
I was trying to the the string representation of the model ("payment" for App.Payment) in order to call store.findAll("payment"). However, looking at the ED source for store, the findQuery function calls modelFor to look up the factory (App.Payment) from the string (payment), unless a factory is already provided. And the factory is easily accessible from the controller by calling this.get('model').type. There's no need to convert it to a string (and back).
Here's the relevant code from the Ember Data source.
modelFor: function(key) {
var factory;
if (typeof key === 'string') {
factory = this.container.lookupFactory('model:' + key);
Ember.assert("No model was found for '" + key + "'", factory);
factory.typeKey = key;
} else {
// A factory already supplied.
factory = key;
}
factory.store = this;
return factory;
},

Twitter Typeahead remote

I am trying to use Twitter typeahead but I am facing a problem. I don't know how typeahead passes the string to the server. Is it through a GET parameter? If so, what is the name of the parameter?
Easiest through a GET parameter, you can choose whatever parameter you want.
In JS:
$('#search').typeahead({
name: 'Search',
remote: '/search.php?query=%QUERY' // you can change anything but %QUERY, it's Typeahead default for the string to pass to backend
});
In PHP (or whatever backend you have):
$query = $_GET['query'];
Hope you get the basic idea.
You might want to consider something like this, it is a very basic remote datasource example. The get parameter in this example is 'q'
// Get your data source
var dataSource = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('value'),
queryTokenizer: Bloodhound.tokenizers.whitespace,
remote: {
url: 'path/to/your/url/json/datasource/?q=%QUERYSTRING',
wildcard: '%QUERYSTRING'
}
});
// initialize your element
var $typehead = $('#form input').typeahead(null, {
source: dataSource
});
// fire a select event, what you want once a user has selected an item
$typehead.on('typeahead:select', function(obj, datum, name) {
//your code here
});
////////////////////////////////////
# in python (django) we get a query string using the request object passed through a view like this
query = request.GET.get('q') or ""
//the caveat [or ""] is just to prevent null exceptions
///////////////////////////////////
# using php
$query = ($_GET['q']) ? $_GET['q'] : "";

create path helper, pass hash to handlebars helper or concatenate string

I was looking for a way to create a path helper in handlebars which generates a url to a specific page. I need to be able to pass a route name and the params needed to generate the route. SO first i was looking to pass a hash to the helper ... but this isn't possible because you can't create this inside the handler template. Now the syntax is like this:
{{{path 'some_path_name' 'foo=bar' }}}
and this seems to work but now i have an issue with that i can't concatenate strings inside the template. Any idea what's the best way to do this? The only option i see now is that i create the params inside my javascript code ... but i don't really like this, i wan't to be able to specify it in the template.
I have a mapping somewhere which maps some_path_name to /path-name/:foo ... so i want the path helper to create /path-name/bar.
kind regards,
Daan
This code should work, but you have to add some extra validation.
var routes = {
'some_path_name': '/path-name/:foo'
};
Handlebars.registerHelper('path', function (routeName, options) {
var route,
params;
if (!routes.hasOwnProperty(routeName)) return;
route = routes[routeName];
params = options.hash;
for (var param in params) {
var value = params[param];
route = route.replace(':'+ param, value);
}
return route;
});