Angular 5 viewchild работает только один раз - PullRequest
0 голосов
/ 05 мая 2018

чтобы получить представление о моем вопросе, вот объяснение того, что происходит, а что нет:

У меня есть функция загрузки, которая загружает файлы .zip, получает весь HTML-код, изображения и преобразует его в строки. Для каждой загрузки это повторяется, после этого, когда я загружаю этот файл .zip, он всегда извлекает его и преобразует весь его контент в строку ->, и я помещаю его в. Проблема в том, что он работает только один раз (помещая строки в iframe).

Вот как это работает:

Я получаю zip-файлы и вызываю ShowVisualContent () для преобразования всего его содержимого в строки. Все строки находятся в моем navService -> this.html: string;

   this.uploads = this.db.list(`profile/${this.auth.userId}/projects/${this.projectId}`).snapshotChanges().map((actions) => {
      return actions.map((a) => {
        const data = a.payload.val();
        this.navSrv.showVisualContent(data.url, data.name);
        const $key = a.payload.key;
        const $ref = a.payload.ref;
        return { $key, ...data, $ref };
      });
    });

Тогда в моем компоненте я получаю html: string;

 @ViewChild('html') html: ElementRef;
 loadHtml(){

    setTimeout(()=> {
      this.html.nativeElement.src = 'data:text/html,' + encodeURIComponent(this.navSrv.html);
    },4000);
    console.log("Loading html into iframe now")
  }

И загрузите его в html следующим образом:

<div  *ngFor="let upload of uploads | async">
  <iframe style="min-width:1300px;min-height:800px;" id="framex" #html scrolling="no" frameborder="0"></iframe>
 </div>

Основная проблема в том, что когда у меня на одной странице загружено много zip-файлов, я получаю только 1 с преобразованными html-строками.

Как сделать так, чтобы this.html был во всех не только в одном.

Как получить значение в виде массива из каждого вызова функции:

html: string;
      this.html = xmlDoc.documentElement.innerHTML; 

(это та часть, где я поместил весь html в строку this.html, и он получил только последнее значение.)

Как получить все HTML в виде массива?

это функция, где я получаю innerHTML всех .zip файлов:

html:string;


public showVisualContent(contentUrl:string, fileName:string) {
    console.log(contentUrl);
    console.log(fileName);
    let fileInfo = getFileInfo(fileName);
    if(fileInfo) {
      switch(fileInfo.type) {
        case 'archive' : {
          getAllFileContentsFromRemoteZip(contentUrl, (files) => {
            //TODO: Remove timeouts. This is just a temporary option for demonstration purposes.
            //Also this is a massive function that must be separated into multiple functions
            setTimeout(() => {
              let storageRef = firebase.storage().ref();
              for(let i = 0; i < files.length; i++) {
                if(files[i].fileInfo.type == 'image') {
                  // Create a storage reference from our app
                  // Create a reference with an initial file path and name
                  let imageRef = storageRef.child(files[i].fileInfo.fileName);
                  files[i].url = imageRef.getDownloadURL().then((url) => {
                    return url;
                  });
                }
              }

              setTimeout(() => {
                for(let i = 0; i < files.length; i++) {
                  //console.log(files[i].fileInfo.fileName);
                  //console.log(files[i].url);
                  if(files[i].fileInfo.type == 'web') {
                    let parser = new DOMParser();
                    let xmlDoc = parser.parseFromString(files[i].content, "text/html");
                    //scripts
                    let scriptElements = xmlDoc.getElementsByTagName('script');
                    for(let j = 0; j < scriptElements.length; j++) {
                      let attr = scriptElements[j].getAttribute('src');
                      if(attr) {
                        for(let k = 0; k < files.length; k++) {
                          if(attr.includes(files[k].fileInfo.fileName)) {
                            scriptElements[j].removeAttribute('src');
                            scriptElements[j].innerHTML = files[k].content;
                          }
                        }
                      }
                    }
                    //styles
                    let linkElements = xmlDoc.getElementsByTagName('link');
                    for(let j = 0; j < linkElements.length; j++) {
                      if(linkElements[j].getAttribute('rel') == 'stylesheet')
                      {
                        let attr = linkElements[j].getAttribute('href');
                        if(attr) {
                          for(let k = 0; k < files.length; k++) {
                            if(attr.includes(files[k].fileInfo.fileName)) {
                              //do stuff
                              let parentElement = linkElements[k].parentElement;
                              if(parentElement) {
                                let styleElement = parentElement.appendChild(xmlDoc.createElement('style'))
                                styleElement.innerHTML = files[k].content;
                              }
                            }
                          }
                        }
                      }
                    }

                    //images
                    let imgElements = xmlDoc.getElementsByTagName('img');
                    for(let j = 0; j < imgElements.length; j++) {
                      let attr = imgElements[j].getAttribute('src');
                      if(attr) {
                        for(let k = 0; k < files.length; k++) {
                          if(attr.includes(files[k].fileInfo.fileName)) {
                            //do stuff
                            //imgElements[k].setAttribute('src', 'data:image/' + files[k].fileInfo.ext + ';base64,' + files[k].content);
                            imgElements[k].setAttribute('src', files[k].url.i);
                          }
                        }
                      }
                    }
                    //console.log(xmlDoc.documentElement.innerHTML);
                    this.html = xmlDoc.documentElement.innerHTML;
                    for(let j = 0; j < files.length; j++) {
                      if(files[j].fileInfo.type == 'image') {
                        let strings = getStringsToReplace(files[j].fileInfo.fileName, this.html);
                        for(let k = 0; k < strings.length; k++) {
                          this.html = this.html.replace(strings[k], files[j].url.i);
                          this.html = this.html.replace('/' + strings[k], files[j].url.i);
                        }
                      }
                    }
                   // console.log(this.html);
                  }
                }
              }, 500);
            }, 1000);
          });
        }
        case 'web' : {
          //show simple html here. Unlikely to happen
        }
        case 'image' : {
          //show image here
        }
      }
    }
  }

1 Ответ

0 голосов
/ 05 мая 2018

ViewChild по своему дизайну получает один экземпляр, используйте viewChildren:

@ViewChildren('html') htmls: QueryList<ElementRef>;
loadHtml(){

  setTimeout(()=> {
    this.htmls.map((elem) => {
       elem.nativeElement.src = 'data:text/html,' + encodeURIComponent(this.navSrv.html);
    }
  },4000);
  console.log("Loading html into iframe now")
}

для лучшего понимания ViewChild & ViewChildren, просмотрите список запросов в этой статье https://netbasal.com/understanding-viewchildren-contentchildren-and-querylist-in-angular-896b0c689f6e

...