Bindings on ObjectController - Ember.js - binding

When you try adding a binding to an ObjectController it doesn't work.
App.FailController = Em.ObjectController.extend({
content: null,
myBinding: "App.router.myController" // <-- fails
});
Error:
Uncaught Error: assertion failed: Cannot delegate set('my', ) to the 'content' property of object proxy <.FailController:ember154>: its 'content' is undefined.
It tries adding it to the content property.
jsFiddle: demo

credits: to caligo-mentis who answered this over at github.
ObjectProxy delegates any call to set to the content property unless a property with the same name exists on the ObjectProxy instance. The simple solution is to define a property with the desired name prior to declaring the binding.
App.FailController = Em.ObjectController.extend({
my: null,
myBinding: "App.router.myController" // <-- works
});
jsFiddle: demo

Alternative solution:
App.FailController = Em.ObjectController.extend({
content: Ember.Object.create(),
my: function() {
return App.router.myController;
}.property('App.router.myController')
});
or better:
App.FailController = Em.ObjectController.extend({
content: Ember.Object.create(),
my: Ember.computed.alias('App.router.myController')
});

Related

OData Model Display Property from first line

I'm using an OData Model from my SAP Gateway:
var oModel = new sap.ui.model.odata.ODataModel(url);
this.setModel(oModel, "model");
Now I have the requirement to display a property from the first line of an EntitySet.
I tried it with the following code in my XML view but without success:
<Text text="{model>/ZLLEDATSet/0/Date}" />
I thought the syntax should be "modelname>/entitySet/index/PropertyName".
Based on the answer from #SiddP: I tried the following but I get the error
Uncaught [object Object]
<Text text="{
path: 'model>/ZLLEDATSet',
formatter: function(value) {
return value[0].Date;
}
}"/>
Try this instead.
text:{
path: '/ZLLEDATSet',
formatter: function(value){
return value[0].Date;
}
}
The above code in your question just works fine. See the jsbin :http://jsbin.com/kobocidose/edit?html,js,output
If you still get error just place alert(JSON.stringify(oModel.getData())); to check if the data is properly set to the model.There is a good chance the your data would show null.

Why is should.be.type() failing with "TypeError: (intermediate value).should.be.type is not a function"

I do not understand why the following test is failing with the error:
TypeError: (intermediate value).should.be.type is not a function
describe('#Option object', function() {
it('returns value as whatever type was passed to the constructor', function() {
var o = function() {
this.getValue = function() {
return new Date();
}
};
var i = new o();
i.getValue().should.be.type('Date');
})
});
I've read [most] of the Should.js documentation but I must be missing something. Can anyone tell me what is wrong with my test?
Actually only one thing wrong. You read not should.js docs, but unit.js docs - it is not related to should.js at all.
Correct link.
Correct code will be:
i.getValue().should.be.instanceOf(Date);
or
i.getValue().should.be.Date();

SAPUI5 tile container OData binding with filters

I am trying to display the data from a OData service into a tile where I need to pass some filters to the OData service. I am using the below code however I am getting the error "No template or factory function specified for bindAggregation function of tileContainer".
var tileContainer = new sap.m.TileContainer("tileContainer",{
height:"80%",
allowAdd : true,
editable : false
});
var templateTile = new sap.m.StandardTile("tileTemplate",{
title : 'Orders',
number:'{COUNT}',
info:'Number of Orders',
icon:"sap-icon://bar-chart",
});
oModel = sap.ui.getCore().getModel();
tileContainer.setModel(oModel);
tileContainer.bindAggregation('tiles',{path : "/OrderSet", filters: [f1, f2]}, templateTile);
new sap.m.App({
pages : new sap.m.Page({
enableScrolling : false,
title : "tile container",
content : [tileContainer]
})
}).placeAt("content");
Can some one tell me what am I doing wrong here.
bindAggregation has two parameters; sAggregationName and oBindingInfo and in your code template is passed outside the oBindingInfo object, hence it is not available, which is reason for your error.
You can also pass individual parameters instead of passing them in oBindingInfo object. But in that case sequence of parameters has to be maintained.
Update bindAggregation method's parameter syntax with this
tileContainer.bindAggregation("tiles",{
path: "/OrderSet",
filters: [f1, f2],
template: templateTile
});

Splitting Yeoman prompts into multiple separate groups

how would one split a yeoman prompt into parts?
I have a rather extended prompt that i'd like to split into parts with a title for each part.
CSS
- prompt1
HTML
-prompt 2
Something like this:
prompt1: function(){
var done = this.async();
condole.log('title 1');
var prompts = [{
name: 'prompt1',
message: 'Prompt 1:',
}]
},
prompt2: function(){
var done = this.async();
condole.log('title 2');
var prompts = [{
name: 'prompt2',
message: 'Prompt 2:',
}]
},
Thanks!
Update as #Deimyts notes in the comments, the original code stopped working. This is due to API changes in Inquirer.JS documented here.
The base API interface is now inquirer.prompt(questions).then(). There's no more callback function.
Any async question functions is taking a promise as return value instead of requiring this.async().
In a nutshell, instead of using the old var done = this.async() API and resolving the prompt inside the callback with done() just return a promise from the prompting functions (see docs).
prompt1: function() {
this.log("HTML")
return this.prompt([
// configure prompts as before
]).then(function (answers) {
// callback body as before, but no more calling done()
}.bind(this));
},
For more details see #Deimyts answer below.
Yeoman uses a run loop with certain predefined priorities that you can use to put your actions into. As mentioned in the ☞ docs you can group several methods at one priority. Here is a snippet to illustrate a generator with prompts split into two groups HTML and CSS:
'use strict';
var generators = require('yeoman-generator');
module.exports = generators.Base.extend({
constructor: function () {
generators.Base.apply(this, arguments);
},
prompting: {
prompt1: function() {
this.log("HTML")
var done = this.async();
this.prompt([{
type : 'input',
name : 'foo',
message : 'Foo',
}, {
type : 'input',
name : 'bar',
message : 'Bar'
}], function (answers) {
this.foo = answers.foo;
this.bar = answers.bar;
done();
}.bind(this));
},
prompt2: function() {
this.log("CSS")
var done = this.async();
this.prompt([{
type : 'input',
name : 'bam',
message : 'Bam',
}], function (answers) {
this.bam = answers.bam;
done();
}.bind(this));
}
},
configuring: function () {
console.log(this.foo, this.bar, this.bam);
}
});
Using this feature of Yeoman you could modularize your code even further, e.g. by putting your different prompts in separate code files and require / import them into your generator file. But basically the above snippet should do the trick.
Let me know if that helps.
The previous answer wasn't working for me until I made several modifications to the example code.
I can't be 100% certain, but I believe that the difference might be due to differing versions of the yeoman-generator module. So, I'm recording this here in case anyone else runs into the same issue.
For reference, I'm using yeoman-generator v0.23.4, yo v1.8.4, node v6.2.2, & npm v3.9.5.
Modifications:
Remove all instances of var done = this.async(); and done().
The async() function was causing the generator to exit after prompt1, and never run prompt2 or the configuring function.
Add return before calling this.prompt();
Removing async() causes the generator to rush through the prompts without waiting for an answer. Adding return fixes this.
Replace the callback function inside this.prompt() with .then().
Before making this change, the generator would run through the prompts correctly, but would not save the answers, and configuring would simply log undefined undefined undefined.
Original: this.prompt(prompts, callback(answers).bind(this))
Revised: this.prompt(prompts).then(callback(answers).bind(this));
Full Example:
'use strict';
var generators = require('yeoman-generator');
module.exports = generators.Base.extend({
constructor: function () {
generators.Base.apply(this, arguments);
},
prompting: {
prompt1: function() {
this.log("HTML")
return this.prompt([{
type : 'input',
name : 'foo',
message : 'Foo',
}, {
type : 'input',
name : 'bar',
message : 'Bar'
}]).then(function (answers) {
this.foo = answers.foo;
this.bar = answers.bar;
}.bind(this));
},
prompt2: function() {
this.log("CSS")
return this.prompt([{
type : 'input',
name : 'bam',
message : 'Bam',
}])
.then(function(answers) {
this.bam = answers.bam;
}.bind(this));
}
},
configuring: function () {
console.log(this.foo, this.bar, this.bam);
console.log('Config: ', this.config);
},
});

Backbone callback functions, success not triggering code

I'm doing a simple AJAX call to append an album's tracks in an unordered list. It will append the tracks on the second click with this code:
window.app.views.AlbumView = Backbone.View.extend({...
events: {
'click .queue-add' : 'selectAlbum',
'click .show-tracks' : 'showTracks',
'click .hide-tracks' : 'hideTracks',
},
showTracks: function(){
_this = this
this.model.getTracks().forEach(function(track){
_this.$el.find('.tracks').append("<li>"+track.attributes.title+"</li>");
});
},
Clearly the tracks hadn't been fetched in time for the first click so I added a callback function to the showTracks method like so:
showTracks: function(){
_this = this
this.model.getTracks({
success: function(tracks){
console.log(tracks);
tracks.forEach(function(track){
_this.$el.find('.tracks').append("<li>"+track.attributes.title+"</li>");
});
}
});
},
Yet it won't enter the block and the console.log(tracks); puts nothing to the console.
Any tips would be really awesome here, thanks!!
app.models.Album = Backbone.Model.extend({
....
getTracks: function() {
this.tracks.fetch();
return this.tracks
},
....
});
I couldn't find where did you invoke that callback. you may need modify "getTracks" method like this:
getTracks: function(callback) {
this.tracks.fetch();
callback(this.tracks); //you need to invoke the callback before return
return this.tracks;
}
This is called "callback pattern", google it will find more.
and the backbone model's fetch method accept option argument, It is a object with two keys -- success and error -- both are function. If you provide this argument, backbone will call them automatically.
hope this help.

Resources