Darshan
Darshan

Reputation: 1011

Ember 2.3 how to use itemControllers in each loops?

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?

Upvotes: 0

Views: 351

Answers (1)

kiwiupover
kiwiupover

Reputation: 1780

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}}

Upvotes: 3

Related Questions