简体   繁体   中英

ember component is passing param by reference in {{#each}}

It may help to follow along with this CodePen . Click the icons.

I have a list of items, each rendered using the ItemIndexComponent, which has a property, controls , that is an array of objects, each of which describes an icon to display, action to be taken, and a state (true/false). The idea is that the controls are passed into a configurable ToolboxMenuComponent that doesn't have any logic about what actions to perform nor icons to display. It receives a click from its child component, which passes up the corresponding control object.

The toolbox then toggles the state on the control before passing that, along with the item, further up the chain to the ItemIndexComponent. Which then examines the control to see which property to change on the item. That all works great, except ...

The problem I'm having is that the same controls array is passed to each item. So, if I click on the edit icon, the "editing" property on that item changes -- colour turns green. But when I click the edit icon for any other item, nothing happens because the "edit" control state is already true , is subsequently toggled, then sent up the chain, resulting in no change to the second item, whose state is already false . If I click the second item's icon again it changes, of course, because the state had previously been toggled.

I understand what's happening but I'm buggered to figure out how to handle this with Ember. How can I pass each item its own controls array whilst keeping the Toolbox agnostic? That is, I want it to know only that controls has those three properties, that state should be toggled, and that it should pass back item and not know anything about item nor toggle the item properties itself. But each item should have its own controls and thus mind its own state for each control.

I swear, every time I post to SO, it's after hours of futility. Then, while putting together the question I go through a half-dozen attempts. And then I post, and the solution bangs me square between the eyes.

Because ToolboxMenu already knows about the state property there's no harm in using that. The answer was to set an instance property on the child ToolboxMenuItem based on controls.state, then toggle that and pass that up the chain. Now, controls.state becomes defaultState , is used precisely once and then ignored. Only the action need be passed up, not the entire control object.

(I had to use mode as the child component property because Ember was complaining about a deprecated state member.)

App.ToolboxMenuComponent = Ember.Component.extend({
  actions: {
    toggleTool: function(action, mode) {
      this.sendAction("action", this.get("item"), action, mode);
    }
  }
});

App.ToolboxMenuItemComponent = Ember.Component.extend({
  mode: null,
  didInsertElement: function() {
    this.set("mode", this.get("control").defaultState);
  },
  actions: {
    click: function() {
      let mode = this.get("mode");
      this.set("mode", !mode);
      this.sendAction("action", this.get("control").action, this.get("mode"));
    }
  }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM