3

I have a list of entries. When I click on such an entry a HTTP request is done, data will be loaded and presented in a table. So far so good.

Now I try to create an export function to output all tables at once. The abstracted code looks like this:

this.objectlist.forEach(entry => {

    this.getDataFromHTTP(entry).subscribe(response => {
        tabledata.push(this.getTableDOM());
    })

})

In the function getTableDOM() I do something like let table = document.getElementsByClassName(data.classname);. The code itself runs when I click every entry. But it doesn't work within the forEach().

The real problem is that the getTableDOM() returns an empty result, because the DOM isn't ready when it is called.

So my question is: how can I wait until DOM changes are done before I call getTableDOM(). Or maybe my approach to achieve my goal is completely wrong. But if so: how can I do it otherwise?

Thx for your help! Lars

Lars
  • 920
  • 1
  • 14
  • 34
  • have you try ` ngAfterViewInit()` – Bhagwat Tupe Mar 31 '19 at 10:00
  • `ngAfterViewInit()` is called just once after the initial view is ready. In my case the view is rendered and `ngAfterViewInit()` has already been called whenI click the export button. – Lars Mar 31 '19 at 10:08
  • Would you mind creating a demo example on stackblitz.com ? That could give us more insight – Shashank Vivek Mar 31 '19 at 10:39
  • @ShashankVivek, I thought about, but the code is a bit too complex for a demo and a simplification is not that easy. Unfortunately! – Lars Mar 31 '19 at 10:41
  • @LarsHagen why don't you use a promise to hold loading the DOM until data is received. – Azkar Moulana Mar 31 '19 at 11:51
  • @AzkarMoulana please can you give an (abstract) code example? – Lars Mar 31 '19 at 12:38
  • Your questions isn't clear. After http request data is presented in table. Fine. My question is when do you call, say, export() function. In the code snippet you have provided for export function, why is there a `getDataFromHTTP` what is the role of http call in exporting? What is `objectlist`? Sorry but I cant make sense of the snippet you have provided. – dasfdsa Mar 31 '19 at 13:42
  • @dasfdsa, well 'ok' my code snippet is really just a small "abstract" piece of code. Let me try to explain: `objectlist` contains a list of `ID`s which are used as parameters for the HTTP calls. E.g. `http://www.example.com/rest/get/1` where `1` is an `ID`. Now I have a button that calls an `export()` function. My goal is - when pressing the button - the all `ID`s from `objectlist` are loaded - one after each other. But finally, I need the DOM of the tables for further processing. I'm using a JS library that expects to get a DOM to export it to Excel. – Lars Mar 31 '19 at 14:23
  • Seems like a good use case for something like [forkJoin](https://www.learnrxjs.io/operators/combination/forkjoin.html). – alphapilgrim Mar 31 '19 at 14:51

3 Answers3

1

Please see this DEMO I've created, hopefully, it'll get you going in the right direction. Like others have mentioned from what you've provided it's difficult to get the full picture. I think what you're looking for is something like OnChanges, I've included relevant example code below. I've also included in the demo a forkJoin example.

import {
  Component,
  Input,
  OnChanges,
  SimpleChanges
} from '@angular/core';

@Component({
  selector: 'on-change',
  template: `
        <pre>
            {{changes | json}}
        </pre>
    `
})
export class OnChangeComponent implements OnChanges {
  @Input() data: any;
  changes;
  constructor() {}

  ngOnChanges(changes: SimpleChanges) {
    this.changes = changes;
  }
}
alphapilgrim
  • 3,761
  • 8
  • 29
  • 58
  • This is an interesting approach I never thought about. I will give it a try. Please can you provide the full source code of the Demo. I'd like to see how you use the forkjoin. I can "only" see the working example. – Lars Mar 31 '19 at 16:30
  • @LarsHagen just click on the word demo, should take you to the full demo. Where you can fully interact with – alphapilgrim Mar 31 '19 at 16:32
  • I did. What happens is that a white screen with the running demo opens - and only the demo. But there is no source code visible. – Lars Mar 31 '19 at 16:35
  • @LarsHagen https://stackblitz.com/edit/angular-jgrtwz?file=src%2Fapp%2Fonchanges.component.ts – alphapilgrim Mar 31 '19 at 16:41
  • I will test your approach within the next days (before I have to go on a business trip). If it works I will do it for sure. – Lars Mar 31 '19 at 20:32
0

You shouldn't use DOM as a source of data like you are doing. Anyways, you can detect the changes manually to render the DOM and in next tick export the content.

constructor(private changeDetector : ChangeDetectorRef) {}

this.objectlist.forEach(entry => {
    this.getDataFromHTTP(entry).subscribe(response => {
        this.changeDetector.detectChanges();//if using push stratagy
        setTimeout(_=>tabledata.push(this.getTableDOM()));
    })
})

Also check this question

You can mark your tables and access them using viewChildren

@ViewChildren("mytable") mytable;

this.mytable.changes.subscribe((el)=>{
    /*check if desired table node exists on el*/
});
dasfdsa
  • 7,102
  • 8
  • 51
  • 93
-3

This will check every 2 secs ...

public static void AngWait(){
    WebDriverWait jsWait jsExec = (JavascriptExecutor) driver;
    String angular5Check = (String) jsExec.executeScript("return getAllAngularRootElements()[0].attributes['ng-version'].value");
    System.out.println(angular5Check);
    if (angular5Check != null) {
        do {
            angularPageLoaded = (Boolean) jsExec.executeScript("return window.getAllAngularTestabilities().findIndex(x=>!x.isStable()) === -1");
            System.out.println("in loop => "+angularPageLoaded);
            Thread.sleep(2000);

        } while (!angularPageLoaded);

        System.out.println("outside loop => "+angularPageLoaded);
    }

}
Daniel
  • 951
  • 7
  • 20
  • What does it have to do with WebDriver? oO – Slava Fomin II Jan 22 '20 at 16:50
  • while the webpage is loading, the angular wait will keep on checking in every 2 secs whether the loader is rolling or not.. Once the loader is gone, then it will assume that the next page/ event is ready. – user2754918 Mar 11 '20 at 07:57