Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there any event to notify when aurelia finished dynamic DOM operation or binding changed? #132

Closed
liuyuanhuo opened this issue Jul 9, 2015 · 5 comments

Comments

@liuyuanhuo
Copy link

I use material-design-lite css style in Aurelia.

As description in GETTING STARTED/Use MDL on dynamic websites
Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function.

code like below, mdl-js-ripple-effect in <li repeat.for='i of 10' ><button...will not work when after click on Add button after page load. mdl-js-ripple-effect * need to call componentHandler.upgradeElement or componentHandler.upgradeDom()* after <button id='Add'clicked and aurelia finished dynamic DOM operation .

Is there any event to notify when aurelia finished dynamic DOM operation or binding changed?

    <button id='Add' type='button' click.delegate='nextButtonEffective()' class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect" >Button ${iButtonEffective} Got Effect, Click to Next Button</button>
    <ul>
      <li repeat.for='i of 10' >
        <button href='' class="mdl-button mdl-js-button mdl-button--raised ${i==$parent.iButtonEffective?'mdl-button--colored mdl-js-ripple-effect':''}">${i}</button>
        <br/>
      </li>
    </ul>
export class Welcome{
  iButtonEffective = 1;

  nextButtonEffective()
  {
    this.iButtonEffective ++;
    if(this.iButtonEffective >= 10)
    {
    this.iButtonEffective %= 10;
    }
  }
@liuyuanhuo liuyuanhuo changed the title Is there any event to notify when aurelia finished dynamic DOM operation? Is there any event to notify when aurelia finished dynamic DOM operation or binding changed? Jul 9, 2015
@liuyuanhuo
Copy link
Author

reply by EisenbergEffect jdanyow on https://gitter.im/Aurelia/Discuss

EisenbergEffect
@liuyuanhuo There is no event that fires every time there is a dynamic dom update. The easiest way to handle this is to create custom elements or custom attributes that encapsulate the UI library you are using. Then they can leverage the attached and detached hooks directly.
@liuyuanhuo That said, you could set up a MutationObserver yourself that watched for dom updates and triggered the library.
More or less, that is what web components polyfills do.

jdanyow
@liuyuanhuo you could also create a custom attribute that calls the necessary "upgrade" code in it's "attached" method. This can be a pain because you need to remember to add the custom attribute on every element that needs upgrading. I used this approach here (look for the materialize attributes throughout the html).

@grantcarthew
Copy link

Is this still the case with Aurelia? I am using slick and need to refresh or update slick when a new item is added to its children. This is bound to a VM through the repeat.for method.

@EisenbergEffect
Copy link
Contributor

You could easily create a custom attribute that you could place on the repeat item template that would fire the event you want.

@BrightShadow
Copy link

But is there ANY best practices in Aurelia to handle such cases?
I'm using kendo.ui and initialization of such controls could be started only after the DOM was generated. Have you some good approaches, practices to do it good?

I'm also wondering if it could be just an app architectural case. If we want to do it this way we should create a custom component initializing the dropDown or other kendo control, and then there are no problems at all. What do you think?

@Jrousell
Copy link

Jrousell commented Apr 21, 2016

I had this issue today with masonry which applies its layout after the DOM has loaded. As suggested, I just created a custom attribute and attached it to the repeating element:

<div class="grid">
    <div class="grid-item" repeat.for="row of projects" >
        <card class="drag-source" title="${row.title}" customer="${row.customer}" 
project-attribute.bind>  
        </card>
    </div>
</div>

Then, in the custom attribute bind method of the custom attribute checked to see if the DOM element being added was the last, and if so applied the masonry layout.

bind(bindingContext, overridingContext) {
    if (overridingContext.$last === true) {
        // masonry stuff here
    }

At first seemed a bit odd, but on reflection it's much nicer not to clutter the view model with DOM manipulation stuff which is basically what masonry is doing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants