I have two component
<div class="input__wrapper">
<multi-select onChange("setLanguages") name="language" multiple options=state.languageOptions value=state.languages></multi-select>
</div>
multi-select.marko
<div class="multi-select">
<div class="multi-select__items">
<div class={'multi-select__item': true, 'multi-select__item_active': component.isActive(value)} for(value, option in input.options) onClick("selectItem", value)>
${option}
</div>
</div>
</div>
Before data was changed, component renders into next code with H3 tags
<h3 class="multi-select" id="b1-_r0-c0-0[0]"><div class="multi-select__items"><div class="multi-select__item multi-select__item_active">All</div></div></h3>
After data changing
<div class="input__wrapper"><div class="multi-select" id="b1-_r0-c0-0[0]"><div class="multi-select__items"><div class="multi-select__item multi-select__item_active">All</div></div>
This bug can be reproduced in template with include and if tags combination . In some cases (when template data in child components don't changed) morphdom, when tagName was changed, don't recreate element, and previous tagName remains unchanged. I try to create more clear test case
I made an example of a code which reproduce this bug.
layout.marko
class {
onCreate(input) {
this.state = {
page: '1',
}
}
switchPage(currentPage) {
this.setStateDirty('page', currentPage);
}
}
<button onClick("switchPage", '1')>Page 1 ${ state.page === '1' ? 'active' : ''}</button>
<button onClick("switchPage", '2')>Page 2 ${ state.page === '2' ? 'active' : ''}</button>
<div>
<c1 if(state.page === '1')><@title>Page 1 TITLE</@title></c1>
<if (state.page === '2')>
<c2><@header>Page 2 TITLE</@header></c2>
</if>
</div>
c1.marko
class {
}
<div>
<h1 if(input.title)>
<include(input.title)/>
</h1>
</div>
c2.marko
class {
}
<header if(input.header)>
<div class="container">
<include(input.header) />
</div>
</header>
When page state changed to '2', tagName h1 in visible component still preserved. I made short video with example
https://media.giphy.com/media/xTkcEwgtAzx1xYBTEY/giphy.gif
If tagName for header tag switch to div tag, all worked normally. Also it worked correctly, if i remove class in c1 or c2 component, or in both components at once.
@westtrade In the latest beta version (npm i marko@beta) we have some changes to the way templates are compiled and diffed that should solve this. If for some reason that is not the case, let us know and we'll reopen this issue.
In version 4.5.0 I have many bugs (with event listeners, with redrawing all DOM tree - when changed state in deep child component) and one infinite loop which appeared after redrawing components.
A little later I will try to describe the bugs found in more detail
div.dropdown [
class=component.class
role=input.role
onMouseenter("reactOnHover", true)
onMouseleave("reactOnHover", false)
]
This code in nested components will reproduce next error
Cannot read property 'addEventListener' of undefined
at addEventListenerHelper (init-components-browser.js?d148:69)
at addDOMEventListeners (init-components-browser.js?d148:76)
at init-components-browser.js?d148:123
at Array.forEach (<anonymous>)
at initComponent (init-components-browser.js?d148:115)
at Function.initClientRendered [as ___initClientRendered] (init-components-browser.js?d148:155)
at ComponentsContext.___initComponents (ComponentsContext.js?d16e:36)
at RenderResult.afterInsert (RenderResult.js?75f6:46)
at Component.js?851e:483
at Object.batchUpdate [as ___batchUpdate] (update-manager.js?28fc:63)
Current bug was fixed.
Most helpful comment
@westtrade In the latest beta version (
npm i marko@beta) we have some changes to the way templates are compiled and diffed that should solve this. If for some reason that is not the case, let us know and we'll reopen this issue.