0
votes

I have a parent component which has an accordion panel (with multiple/dynamic number of rows)

{{#my-accordion accordionPanels=accordionPanels as |accordion| }}
{{my-details-row section=accordion.props.section removeRow='removeRow'}}
{{/my-accordion}}

The corresponding JS is as below;

accordionPanels: function() {
    var accordionPanels = [];
    var self = this;
    var myRows = this.get('section').myRows;
    myRows.forEach(function(myRow) {
        accordionPanels.pushObject({
            panel: {
                name: myRow.rowId,
                props: {
                    section: myRow
                }
            }
        });
    });

    return accordionPanels;
}.property('section.myRows'),

actions: {
    removeRow: function(row){
        var numberContainers = this.get('section').myRows.length;
        for (var i = 0; i < numberContainers; i++){
            if(this.get('section').myRows.contains(row.name)){
                console.log("row found!");
                this.get('section').myRows.removeObject(row.name);
            }
        }
    },
}   

The child component (my-details-row) code is as below

actions: {
    removeRow: function(row){
        this.sendAction('removeRow', row);
    }
}

The child hbs is as below;

<div class="dataBlockItem">
    {{my-field field=(field-from-section section "SECTION_NAME" "FIELD_NAME") }}
</div>  
{{my-button label="Remove" action="removeRow"}}

Now when the Remove button is clicked, I want the corresponding row to be removed. While I do get the action in the parent (passed from child), even after executing the line

this.get('section').myRows.removeObject(row.name);

The UI does not get updated (i.e. the data changes in the parent do not reflect in the child component)

Do I need to write additional code/logic to be able to reflect the changes on the UI ?

1
Try this.get('section.myRows').removeObject(row.name);, if you want observer and computed property to trigger then you need to use get method.Ember Freak

1 Answers

1
votes

You are on the right track. You should be able to use closure actions to help simplify connecting the parent and child component actions. Please see the below code and a very basic example Ember Twiddle at the link below. Also, you may have seen this, but just in case here is a link to the Ember.js guides that provides an explanation of component actions. Ember Component Actions -version 2.15

Parent component.hbs

{{#my-accordion accordionPanels=accordionPanels as |accordion| }}
  {{my-details-row section=accordion.props.section removeRow=(action 'removeRow' accordion)}}
{{/my-accordion}}

Parent component.js

--here the row can be removed by simply passing the row object itself .removedObject(row)

actions: {
  removeRow: function(row){
    var numberContainers = this.get('section.myRows').length;
    for (var i = 0; i < numberContainers; i++){
      if(this.get('section.myRows').includes(row.name)){
        console.log("row found!");
        this.get('section.myRows').removeObject(row);
      }
    }
  },
}   

Child component.hbs

--here tie the removeRow action to the button component's click event

<div class="dataBlockItem">
    {{my-field field=(field-from-section section "SECTION_NAME" "FIELD_NAME") }}
</div>  
{{my-button label="Remove" click=removeRow}}

Child component.js

--here the removeRow function does not have to be defined.

actions: {
  // No need to define the removeRow function
}

Example Ember Twiddle --using [email protected] to show the rough compatibility of the above approach