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

<compose> content not loaded in DOM when calling from Attached method. #646

Open
Trix3x opened this issue Oct 5, 2018 · 4 comments
Open
Labels

Comments

@Trix3x
Copy link

Trix3x commented Oct 5, 2018

I'm submitting a bug report

  • Library Version:
    au -v 0.35.1

Please tell us about your environment:

  • Operating System:
    Linux (ubuntu) but also under Win10

  • Node Version:
    v10.10.0

  • NPM Version:
    6.4.1
  • Browser:
    all

  • Language:
    ESNext

Current behavior:
Compose content is not ready in DOM for 'attached' method.
It looks like the attached method is called before the composition is done.
If you are using compose as includes only (without view-model) you are not able to get the part of the <compose> DOM.

Expected/desired behavior:

Working example:
https://gist.run/?id=22855ce9b7864f8891a150b8a645b0db
In console you will see <p> element.

Now we have to downgrade the aurelia-templating to version 1.7.0 which works well. (and also related parts)

"aurelia-bootstrapper": "2.2.0",
"aurelia-framework": "1.2.0",
"aurelia-templating": "1.7.0",
"aurelia-templating-resources": "1.6.1",
"aurelia-templating-router": "1.3.1",

How to reproduce:
Install new aurelia project: au new
Keep everything in default.

Once the project is ready, create view template - comp.html:

<template>
  <p id="here">Tadaa</p>
</template>

Use compose element and include the created view to app.html:

<template>
  <h1>${message}</h1>
  <compose view="./comp.html"></compose>
</template>

Next create the attached method and try to get the element from comp.html

export class App {
  message = 'Hello World!';
  
  attached(){
    console.log( document.getElementById('here') );
  }
}

au run and watch the console. You'll see null. :(

  • What is the expected behavior?
    According your documentation:
    attached() - the component is attached to the DOM (in document). If the view-model has an attached callback, it will be invoked at this time.

  • What is the motivation / use case for changing the behavior?
    We are using compose elements as includes and for 3rd party plugins which needs the DOM to be loaded/ready before they work. Now the DOM is not ready when calling it from attached method so the app crashes.

I appreciate any help. ✌️
Thank you very much!

@StrahilKazlachev
Copy link
Contributor

As far as I'm familiar with the CompositionEngine and <compose> it was never guaranteed that the composed View will be attached at the time the parent view is being attached.
Probably when using view only that is not much evident, as when using a view model with an .activate hook.
Regardless of the scenario(view only/view model with view/...), in the end the composition is done by the CompositionEngine.prototype.compose, which is async.
The only change I can think of that can cause this unexpected behavior for you is here, the change where controller.automate is called.

@Trix3x
Copy link
Author

Trix3x commented Oct 5, 2018

Hello,
I'm not familiar how the internal works, I'm just a regular user 😄

I understand what you are trying to say regarding the composition, but I have to put in my 2cents.

It's not the <compose> element that should wait until the parent is attached but it's the parent that should wait until all the children are ready and attached to DOM. And it should not depend whether it's compose or custom element unless you specify that you want it async.
Otherwise I can choose the bind or other method and use the ref which will do the job for the partial view.
I'm starting to think that there is no place where we can call document.getSomething when the DOM is ready because everything starts to be async.

@StrahilKazlachev
Copy link
Contributor

The <compose> element is probably one of the most misunderstood. It can be viewed as a very simplified declarative wrapper of the CompositionEngine. The element itself is attached when the parent is attached. But it can still modify its content/children.

Its purpose is to dynamically compose a View at any time. As such there may be noting to compose at the beginning when the parent is getting attached. Or what is initially composed may change way after the parent has been bound and attached.

There is the CompositionTransaction mechanism to make the parent/s await child compositions, but that involves a view model for the given composition.

@bigopon what do you think about this issue and #633?

@bigopon
Copy link
Member

bigopon commented Oct 5, 2018

I think #633 and this are not related in any way. There are two swap operations going on in this case and neither is instructed to wait for another. First one is of application root composition and 2nd is of <compose/>. If there is a tick delayed in app.attached, it would work as expected since the 2nd _swap from <compose/> will run before the promise inside app.attached. Probably it's something like this:

  • (1) <app/> compose
  • (2) <compose/> compose
  • (3) <app/> _swap ( (4) attached())
  • (3) <compose/> _swap

https://gist.run/?id=91024ababc53d8b990b9e21602b7a165

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

No branches or pull requests

3 participants