Dynamically rendering a component

I want a component to be re-rendered with different attributes on chaninging a controller property. So, I have my code like,

{{#if (eq diffView "type1")}}
   {{comp/mycomp diffId=diffFile.id  diffIdPrefix=diffView view=diffView thisCtrl=thisCtrl commitDiff=diffFile.diff filePath=diffFile.fileName}}
{{else}}
   {{comp/mycomp diffId=diffFile.id  diffIdPrefix=diffView view="line-by-line" thisCtrl=thisCtrl commitDiff=diffFile.diff filePath=diffFile.fileName}}
{{/if}}

Changing the property diffView, throws me error like, vendorrepository.js:13602 Uncaught DOMException: Failed to execute ā€˜removeChildā€™ on ā€˜Nodeā€™: The node to be removed is not a child of this node. at clear(ā€¦) at UpdatableBlockTracker.reset (ā€¦) at TryOpcode.handleException (ā€¦)

This error was inside ember source code. I think there was some error trying to remove the older component. Pls help me out with this issue.

Hi @Mohana_Priya, what version of Ember are you using? (It will be listed as ā€œember-sourceā€ in your package.json)

I think we will need to know more about what comp/mycomp is doing to debug this issue. Can you share its JS and HBS files?

A more typical way to write the code you showed above is

{{comp/mycomp diffId=diffFile.id  
              diffIdPrefix=diffView 
              view=(if (eq diffView "type1") diffView "line-by-line") 
              thisCtrl=thisCtrl 
              commitDiff=diffFile.diff 
              filePath=diffFile.fileName}}
1 Like

I am using ember version 3.3.0. This is the exact code in mycomp.

export default Component.extend({

    didInsertElement() {
        emberUtils.scheduleOnce('afterRender', this, this._render);
    },

    _render() {
        var self = this,
            diffId = self.get('diffId'),
            view = self.get('view'),
            thisCtrl = self.get('thisCtrl'),
            commitDiff = self.get('commitDiff'),
            filePath = self.get('filePath'),
            controller = self._getController();
            
        self.set("controller", self._getController());
        if (!emberUtils.isNone(self.get('diffIdPrefix'))) {
            diffId = self.get('diffIdPrefix') + diffId;
        }
        
        controller.get('appCtrl').convertToHtml(diffId, filePath, commitDiff, view, function(html) {
            if (controller.get('enableDiscussions')) {
                self.get('controller').showFileDiscussions(diffHTML.filePath);
                $("#fc-commentIcon").mouseenter(function() {
                    $("#fc-commentIcon").addClass("show-commentIcon");
                });
                $(".d2h-code-linenumber, .d2h-code-side-linenumber").mouseenter(function() {
                    if ($(this).attr("class").indexOf("d2h-info") !== -1 || $(this).attr("class").indexOf("d2h-cntx") !== -1) {
                        $("#fc-commentIcon").removeClass("show-commentIcon");
                        return;
                    }
                    self.get("controller").set('lineElem', this);
                    $("#fc-commentIcon").addClass("show-commentIcon");
                    $("#fc-commentIcon").css({
                        top: ($(this).offset().top - $("#zc-fileChangeList").offset().top - 10 + $("#zc-fileChangeList").scrollTop()) + 'px',
                        left: ($(this).position().left) + 'px'
                    });
                    $(this).addClass("addCommentLineNumber");
                });

                $(".d2h-code-linenumber, .d2h-code-side-linenumber").mouseleave(function() {
                    $(this).removeClass("addCommentLineNumber");
                    $("#fc-commentIcon").removeClass("show-commentIcon");
                });
            }
        });
    }
});

FYI: convertToHtml in appCtrl will render a thirdparty component. Sorry for poor formatting.

I see. So the issue is almost certainly being caused by that third-party component inside convertToHtml.

If you make changes via didInsertElement, you need to clean them up via willDestroyElement. I think that may resolve your issue. The exception you see is because Ember is trying to tear down your component and itā€™s surprised to find extra stuff inside that was not cleaned up.

1 Like

Re-render works when i switch to other routes and come back to the same route again, I mean the component will be destroyed if i switch to other route then it should work the same now. The problem here is the component is not rendered again in the same route as the older one cannot be destroyed. And thus my question is how it is destroyed when i switch to another route :thinking:

I found a temporary fix for this issue. If i bring the common div inside the conditional block it was working. FYI: issue is not with that thirdparty component since if i replace that thirdparty code with a simple innerhtml manipulation this issue was reproducible.

Before:

<div id="difffiles">
  {{#if (eq diffView "type1")}}
     {{comp/mycomp diffId=diffFile.id  
                   diffIdPrefix=diffView 
                   view=diffView
                   thisCtrl=thisCtrl 
                   commitDiff=diffFile.diff 
                   filePath=diffFile.fileName}}
  {{else}}
     {{comp/mycomp diffId=diffFile.id  
                   diffIdPrefix=diffView 
                   view=diffView
                   thisCtrl=thisCtrl 
                   commitDiff=diffFile.diff 
                   filePath=diffFile.fileName}}
  {{/if}}
</div>

Now:

{{#if (eq diffView "type1")}}
  <div id="difffiles">
     {{comp/mycomp diffId=diffFile.id  
                   diffIdPrefix=diffView 
                   view=diffView
                   thisCtrl=thisCtrl 
                   commitDiff=diffFile.diff 
                   filePath=diffFile.fileName}}
  </div>
{{else}}
  <div id="difffiles">
   {{comp/mycomp diffId=diffFile.id  
                   diffIdPrefix=diffView 
                   view=diffView
                   thisCtrl=thisCtrl 
                   commitDiff=diffFile.diff 
                   filePath=diffFile.fileName}}
  </div>
{{/if}}