How can you modify a Shadow DOM Custom Element after is built?

Viewed 293

I am currently trying to add bold titles to the calcite-block tag in calcite-components

To modify the Shadow DOM you could extend the CalciteBlock class, adding additional properties to modify the rendered element - however, this has proven difficult as I cannot extend the large library without confident knowledge in custom elements.

The other route is to append the b (bold) element after the custom element is built. This is how I have achieved this. First I have added the elements to the DOM through the traditional route.

//On document ready
$(document).ready(function() {

    //Iterate all the items to append to the block
    for (var i = 0; i < class_data.length; i++) {
            
            //Create item (with some misc meta data)    
            var $item = $('<calcite-block-section/>')
                .attr('id', i)
                .attr('color', current_col)
                .attr('title', temp_class.title)
                .text(temp_class.desc);
            
            //Descriptions is the calcite block we are appending to
            $("#descriptions").append($item);
        }
    }
});

Afterwards, I check the MutationObserver to see when the update has fired, and I add the title text to the block. Whilst typically you could set text attribute to the block, the custom element doesn't allow you to set a HTML attribute. In this case, adding a calcite icon.

//Creates Mutation Observor
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

var observer = new MutationObserver(function(mutations, observer) {

    //Queries the document
    $($("calcite-block-section")).each(function(index) {

        //Collects attributes
        var id = $(this).attr('id');
        var color = $(this).attr('color');
        var title = $(this).attr('title');
        
        //Gets shadowDOM for element
        var $elem = $(this)[0].shadowRoot.querySelector('.section-header__text');
        
        var $square = $('<calcite-icon icon="squareArea" scale="m"></calcite-icon>')
            .css('color', color);
        
        var $text = $('<b/>').html('&nbsp;&nbsp;' + title);
        
        //Sets the custom title
        $($elem)
            .append($square)
            .append($text)
    });

    //Removes check
    observer.disconnect();
});

//Runs observer
observer.observe($('#descriptions').get(0), {
    childList: true,
    subtree: true
});

What I have gathered, from testing, is that the MutationObservor does fire, but it does not fire after the custom elements have been rendered. Instead, it runs as soon as the document has loaded. Second, running the query selection in isolation shows that the title creation code does produce the intended result, suggesting the problem is with the timing.

My question is whether this is the best approach to modify custom-element DOM, in particular for adding elements to the block element in Calcite, and why MutationObserverloc fires before the elements have been built.

0 Answers
Related