0

Using the Aurelia JS framework, I need to be able to detect when the results of a repeat.for over elements have been loaded completely into the DOM by code in the parent VM. I know I can inject a listener into a @bindable and trigger the listener on attached(), but that seems very hokey to me.

Any ideas?

Mike Gates
  • 1,874
  • 3
  • 21
  • 40
  • 2
    you could enqueue a microTask that will run after all enqueued microTasks. See http://stackoverflow.com/questions/36049391/is-there-a-callback-or-promise-for-aurelia-show-bind and http://stackoverflow.com/questions/35587033/bindable-changehandler-fires-before-bindings-are-done-updating – Fabio Nov 17 '16 at 05:05
  • This doesn't seem to work when the generated elements are created with . Any way to make that work? – Mike Gates Nov 18 '16 at 05:14
  • Could you reproduce your problem in this gist https://gist.run/?id=c32f322b1f56e6f0a83679512247af7b ? It would be easier to help you – Fabio Nov 18 '16 at 08:07
  • Ok, I added the code that shows the problem to that gist – Mike Gates Nov 18 '16 at 22:21
  • You have to fork it and send me the link – Fabio Nov 19 '16 at 00:49
  • I'll have to do it again. Haven't used gist before. – Mike Gates Nov 21 '16 at 17:32
  • Ok, new gist that shows the problem: https://gist.run/?id=854f38ddfa0abac901ded323b2f3dae7 – Mike Gates Nov 21 '16 at 18:54

1 Answers1

0

The problem is that you are pushing items inside the attached method and you are using dynamic composition, which usually is not a problem but your situation is a bit different. Queuing a micro-task doesn't help because it runs before your view (child.html) is loaded.

There are couple ways to solve the this problem:

1° Solution

Push your items inside bind():

bind() {
  this.items.push({
     view: 'child.html',
     viewModel: new Child('A')
  });  

  this.items.push({
     view: 'child.html',
     viewModel: new Child('B')
   });
}

attached() {

  let container = document.getElementById('container');
  console.log('Height after adding items: ' + container.clientHeight);

  this._taskQueue.queueMicroTask(() => {
    console.log('Height after queued microtask: ' + container.clientHeight);    
  });

  setTimeout(() => {
    console.log('Height after waiting a second: ' + container.clientHeight);    
  }, 1000);

}

Fix the HTML:

<template>
  <div id="container">
    <div repeat.for="item of items">
      <compose view-model.bind="item.viewModel" view.bind="item.view"></compose>
    </div>
  </div>
  <div style='margin-top: 20px'>
    <div repeat.for="log of logs">
      ${log}
    </div>
  </div>
</template>

Running example https://gist.run/?id=7f420ed45142908ca5713294836b2d5e

2º Solution

Do not use <compose>. Compose was made to be used when dynamic compositions are necessary. Are you sure you need to use <compose>?.

<template>
  <require from="./child"></require>

  <div id="container">
    <div repeat.for="item of items">
      <child>${item.data}</child>
    </div>
  </div>
</template>
Fabio
  • 11,892
  • 1
  • 25
  • 41
  • Bind seems to wait for the true height to be available, but I need to be able to check the height at any point after that. I added a click() to the gist that adds another element as an example. – Mike Gates Nov 21 '16 at 22:23
  • As far as not using compose, I need to use compose because my application has different views that need to go in a list depending on model properties (just like in the gist, although the gist just has one view). – Mike Gates Nov 21 '16 at 22:24
  • I've updated my answer and my gist https://gist.run/?id=7f420ed45142908ca5713294836b2d5e with a working solution but there might be better ways to solve this, see if it helps. In the meantime I'll try to find some help – Fabio Nov 22 '16 at 09:32
  • Thanks, Fabio. I thought about the callback way but I didn't want to implement that in all the possible child components, it just seemed like there should be a way to deal with this from the parent level using the framework. – Mike Gates Nov 23 '16 at 00:03
  • I'm digging into it and I also asked for help of the official team. Let's see if I get a solution tomorrow or after tomorrow – Fabio Nov 23 '16 at 00:42