I am using the controller property as array initially the view will render once after updating the array the view is not getting updated.
Eg:
Handlebar:
{{#each records}}
{{name}}
{{/each}}
Controller:
App.recordsController = App.EventHandlerController.extend({
records: null,
actions:{
//stmt1
var array = ["test", "test2"];
this.set('records', array);
//stmt2
array.push("data");
this.set('records', array);
}
});
The view is not getting updated after statement 2 What is the reason for this?
This is failing because it is not valid JavaScript. The object passed to extend is a JavaScript object, which consists of keys and values. After records: null,, you have code that looks like it belongs in some function. You should have seen an error in your console describing this.
Related
Before anyone brings up components, I must state that I am aware that Ember is moving away from controllers and views completely and adopting the component structure. Right now, I am compelled to use controller/view in ember2.3 using the legacy-controller and legacy-view addons that have been provided here:
https://github.com/emberjs/ember-legacy-controllers
https://github.com/emberjs/ember-legacy-views
as part of the process to upgrade to Ember 2.3 (from 1.7).
Now, I have a route called recordTypes, which lists all recordTypes. in the legacy code, each recordType was then associated with an itemController 'recordType'. Like so:
{{#each result in searchResults itemController="recordType"}}
...
{{/each}}
Surprisingly, this legacy syntax for Ember did not render anything to the page, but the following one did:
{{#each searchResults itemController="recordType" as |result| }}
...
{{/each}}
The itemController recordType is a legacy Object Controller and the recordTypes controller itself is a legacy Array Controller.
Now, for each result I have a few actions that can be performed. For example, on clicking the result, the editResultName action was to be fired. This action, in the legacy code, was in the recordType controller. Therefore, clicking the item in the recordTypes page would then defer this action to the recordType controller, which would then happily handle the rest.
This is not being fired in ember2.3, even with the legacy controllers. What surprises me more is that this code can be found in ember-legacy-controller.js
export default {
name: 'ember-legacy-controllers',
initialize: function() {
/**
Adds support for ArrayController in the legacy {{each}} helper
*/
Ember._LegacyEachView.reopen({
_arrayController: computed(function() {
var itemController = this.getAttr('itemController');
var controller = get(this, 'container').lookupFactory('controller:array').create({
_isVirtual: true,
parentController: get(this, 'controller'),
itemController: itemController,
target: get(this, 'controller'),
_eachView: this,
content: this.getAttr('content')
});
return controller;
}),
_willUpdate(attrs) {
let itemController = this.getAttrFor(attrs, 'itemController');
if (itemController) {
let arrayController = get(this, '_arrayController');
set(arrayController, 'content', this.getAttrFor(attrs, 'content'));
}
}
});
}
};
Here, it does have a line that references the itemController. However, when this list of searchResults is rendered, and a result is clicked, the error I get is this:
Nothing handled the action 'editResultName'. If you did handle the action, this error can be caused by returning true from an action handler in a controller, causing the action to bubble.
The action is there for sure, but nothing in the itemController is being recognised. Unfortunately a lot of the legacy code I am updating has itemController loops and therefore it would be immensely helpful to be able to use itemController for the time being.
How can I use itemController like it used to be implemented?
Replacing an itemController.
Create a component from the contents inside the each helper. The itemController would become the js side of the component and the template code the template
From this:
{{#each result in searchResults itemController="recordType"}}
<span>result: {{result.title}}</span>
{{/each}}
To this:
{{#each searchResults as |result| }}
{{result-list-item result=result}}
{{/each}}
I need an explanation for the usage of an itemcontroller in emberJS.
I created a handlebars template that looks like this:
{{#each thing in controller itemController="itemController"}}
{{view "testview" contentBinding="thing"}}
{{/each}}
The testview creates a html table and within the testview I use a second view in a each loop which creates several tr:
{{each item in view.content.thing}}
{{view 'trview' contentBinding="item"}}
{{/each}}
In addition to that I added a property "listOfProperties" (Ember.A()) to the itemController.
I use the click function of the trview to add a value to the "listOfProperties" array of the itemController.
And here I receive an error: If I click on a tr, the value is added to each itemControllers "listOfProperties" array and not only to one "things" itemController.
I'm going to guess since you didn't include your item controller, but it's likely you're running into a reference issue. Array's are a reference and as such are shared across instances of item controllers.
App.ItemController = Em.ObjectController.extend({
setup: function(){
this.set('listOfProperties', []);
}.on('init'),
listOfProperties: null,
});
I want to create a component which needs to generate dynamics links. I tried passing the link data as an array, but this does not work.
var user1 = get("store").find("user", 1);
var data = {link: ["users.show", user1], title: "User1"};
{{#link-to data.link}}{{data.title}}{{/link-to}}
This should be equal to
{{#link-to "users.show" 1}}{{data.title}}{{/link-to}}
How to generate fully dynamic links from a variable?
You can specify an array as params argument into a link-to helper. Similar to nickiaconis' answer answer, but with just the default {{link-to}} helper:
{{#link-to params=data.link}}{{data.title}}{{/link-to}}
...will render something like:
User1
(tested with Ember 2.3.0)
Ember 1.13.x
The LinkComponent, which is what the link-to helper creates for you, is exposed as -link-to. I've created an example of its use here: http://emberjs.jsbin.com/rinukefuqe/2/edit?html,js,output
{{#-link-to params=(unbound link) hasBlock="true"}}
{{title}}
{{/-link-to}}
The params attribute is what the link-to helper normally bundles your positional parameters onto, although you must use the unbound helper here because the LinkComponent expects params to be an array rather than a value binding object. Additionally, the determination of use as block or inline component is not built into components yet, so you must pass hasBlock="true" unless you include the link text as the first parameter in your array.
Ember ≤ 1.12.x
Although it is not done already, you can manually expose the LinkView component, which is the equivalent of the new LinkComponent.
App.XLinkToComponent = Ember.LinkView.extend();
Then use it like:
{{#x-link-to params=link}}
{{title}}
{{/x-link-to}}
Using unbound and hasBlock="true" are not necessary as the internal logic of LinkView differs from LinkComponent.
I think that isn't possible to pass an array, but you can pass each argument directlly, like the following:
route
var user1 = this.store.find('user', 1);
var data = { data: { link: "users.show", model: user1, title: "User1" } };
return data;
template
{{#link-to data.link data.model.id}}{{data.title}}{{/link-to}}
I hope it helps
I'm using a render helper inside a template, which renders a searchbox with a typeahead.
Essentially (code removed for brevity):
script(type='text/x-handlebars', data-template-name='index')
{{render search}}
script(type='text/x-handlebars', data-template-name='search')
{{view App.TaggableInput valueBinding="searchText"}}
Which gives me a SearchController separated from the IndexController.
Inside App.TaggableInput I'm grabbing searchController to do some checking on the keyUp event:
App.TaggableInput = Ember.TextField.extend({
keyUp: function(e){
var controller = this.get('controller');
// Do stuff with the controller
}
});
On Ember RC7, I can access the controller inside theview as you'd expect with this.get('controller').get('searchText').
However in Ember 1.0.0 this.get('controller') returns the view, and whatever I do I can't get searchController.
I can't find any related info on the ember website regarding what's changed or what I'm supposed to do... for now I'm sticking with RC7.
Any ideas? I've spent hours on it this morning and can't figure it out. Thanks.
UPDATE: Fixed!
I swapped out this.get('controller') for this.get('targetObject') and it works as before. Had a peruse through a recent commit in ember source to find it...
Thanks for your suggestions guys!
I guess that in your code
App.TaggableInput = Ember.TextField.extend({
keyUp: function(e){
var controller = this.get('controller');
// Do stuff with the controller
}
});
this line
var controller = this.get('controller');
gets the controller associated to your (subview)
Try to use this line instead to access the route's controller:
var controller = this.get('parentView.controller');
Currently, the {{render}} helper takes 2 arguments, the first is the context, the second is the model.
I recommend using this method and following the naming convention for the model's controller rather than setting the controller explicitly.
You can find the docs here:
http://emberjs.com/guides/templates/rendering-with-helpers/#toc_the-code-render-code-helper
Accessing controllers from views was also being tracked in this discussion:
https://github.com/emberjs/ember.js/issues/1712#issuecomment-31183940
I think Ember has not changed its behaviour. I created a JSBin, where i managed to get the controller successfully.
What i did was creating a simple View and show it via {{render}} helper:
View:
App.FooView = Ember.TextField.extend({
didInsertElement : function(){
console.log(this.get("controller.constructor"));
console.log(this.get("context.constructor"));
}
});
Template:
{{render foo}}
And the first log statement showed an associated controller. Can you see any conceptual difference between my code and yours?
Part of learning Ember.js I am trying to create a Table View in Ember, based on example by Adam.
The issue I am facing is that if I create a seperate controller for the View and include an itemController for the Rows, ember gives following error: Uncaught TypeError: Cannot call method 'lookup' of null ember-1.0.0-rc.6.js:13933
When I debug this I find that in the following code :
controllerAt: function(idx, object, controllerClass) {
var container = get(this, 'container'),
subControllers = get(this, '_subControllers'),
subController = subControllers[idx];
if (!subController) {
subController = container.lookup("controller:" + controllerClass, { singleton: false });
The container is retrieved as null.
Whereas when it is run through ApplicationController, no such issue is there.
JS Fiddle Using ApplicationController for the View and another controller for itemController - Works Fine
JS Bin
in this the item Controller is specified as {{#each controller itemController="tableRow"}} and the controller is App.TableRowController
Here is a very similar JS Bin, JS Fiddle using a seperate TableViewController :
The item controller is similarly specified as {{#each controller itemController='tableRow'}.
A seperate Controller for Table View is binded using : {{view App.TableView controllerBinding="tableViewController"}} and this tableViewController is specified as a property in ApplicationController as :
App.ApplicationController = Ember.ArrayController.extend({
tableViewController: function() {
var tc = Ember.get('App.TableViewController').create();
tc.set('content',Ember.ArrayProxy.create({
content: Ember.A(tableData)})
);
return tc;
}.property()
});
But for some reason, the itemController does not work here.
Here is the JS Fiddle Using seperate Controller for View, but without any itemController - this works fine
Is there anything I am missing in the controller ?
Please help. Thanks.
With Ember most of the time you don't create objects directly, you declare the classes for things like controller, model, etc. And ember creates these objects using an IOC container. Avoid things like Controller.create. Similarly avoid directly controllerBinding instead use needs.
So, instead of providing a controllerBinding pass the content to be rendered by the App.TableView.
{{view App.TableView contentBinding=content}}
The setup of the tableData also belongs in a model() hook. It works in the sample because tableData variable is in scope.
Here's the updated jsfiddle.