2017-07-04 6 views
0

Ich bin neu in Angular, also bitte verzeihen Sie mir, wenn ich don t verwenden Sie die richtige Terminologie.Angular 4: Bind nur einmal zu Methode, die verspricht

Ich versuche, eine Tabelle dynamisch zu erstellen, indem Sie die TD-Daten an einen Methodenaufruf binden. Wie folgt aus:

<tbody> 
    <tr *ngFor="let rw of ParameterRowData" > 
    <td *ngFor="let field of fields" class="lalign" [innerHTML]="getCellData(field, rw.ParameterData)" ></td> 
    <td><a >Edit</a> </td> 
    </tr> 
</tbody> 

Ich tue dies, weil ich nicht die verfügbaren Spalten und Daten kennen, bis sie vom Server zurückgegeben wird. Mein Problem ist, dass die Methode getCellData immer und immer wieder aufgerufen wird. Der Browser friert ein, aber in der Konsole kann ich sehen, dass er immer wieder bis ins Unendliche aufgerufen wird. Ich möchte nur, dass es einmal angerufen wird.

die getCellData Methode ist wie folgt:

getCellData(field: ParamField, fields : ParameterRowFieldContract[]) : Promise<string> 
    { 
     for(var i=0; i<fields.length; i++) 
     {   
      if(fields[i].Name===field.DisplayName) 
      { 
       console.log('a'); 
       if(field.DataType == "FOREIGNKEYLIST") 
       { 
        //getforeign key value to display 
        console.log('b'); 
        var value = this.paramService.getParameterDataWithId(field.ForeignParameter, fields[i].Value) 
        .then(para => {  
         for(var k=0; k<para.ParameterData.length; k++) 
         { 
          console.log('c'); 
          if(para.ParameterData[k].Name===field.ForeignField) 
          { 
           console.log('foreign ='+ para.ParameterData[k].Value); 
           return para.ParameterData[k].Value; 
          } 
         } 
        }); 
        return value; 

       } 
       else 
       {    
        return Promise.resolve(fields[i].Value); 
       } 
      }  
     } 
    } 

Am Ende des Tages möchte ich nur aus dem Dienst im HTML-Element td den zurückgegebenen Wert anzuzeigen. Ich bin bereit, einen alternativen Weg zu gehen, um dieses Problem zu lösen. Die Daten werden nicht bearbeitet, sobald sie in die Tabelle geladen sind, aber ich bin mir nicht sicher, ob eine unidirektionale Bindung mir helfen kann und ich noch nicht verstehe, wie eine unidirektionale oder eine zweiseitige Bindung implementiert werden kann.

Vielen Dank im Voraus für Ihre Unterstützung.

+0

Sie brauchen ein gutes Verständnis der eckigen Konzepte vor dem Erstellen solcher Anwendung. –

+0

Das stimmt. Aber ich wurde in das tiefe Ende geworfen. Das ist meine Chance zu beeindrucken, also keine andere Wahl. – peterpie

+0

Vielleicht könnte ein kundenspezifisches eckiges Rohr eine einfachere Lösung gewesen sein?Wie die letzte Lösung in dieser Frage: [stackoverflow question] (https://stackoverflow.com/questions/34363161/angular-2-displaying-async-object-data-from-promise) – peterpie

Antwort

0

Eine Umgehungslösung gefunden.

Zunächst war ich an einen Ausdruck gebunden, der ein Versprechen zurückgibt. Unter diesem Link Angular Docs die Winkel Team rät von der Verwendung von komplexen epressions hier:

Der Ausdruck könnte so etwas wie getFoo() aufrufen. Nur Sie wissen, was getFoo() tut. Wenn getFoo() etwas ändert und Sie mit dem etwas verbunden sind, riskieren Sie eine unangenehme Erfahrung. Winkel kann den geänderten Wert anzeigen oder nicht. Angular kann die Änderung erkennen und einen Warnfehler ausgeben. Im Allgemeinen bleiben Sie bei Dateneigenschaften und bei Methoden, die Werte zurückgeben und nicht mehr.

Um es einfach zu halten, musste meine Methode eine Zeichenfolge zurückgeben.

Wie für die fremden Daten, prefetchte ich es auf ngOnInit und speicherte es in einem mehrdimensionalen (2D) Array, Ausländer.

foreigners = []; 
foreignParamNames : string[]; 

Dann in ngOnInit ich sie mit Daten füllen. Die ForeignParamNames sollen den Index für das Multi-Demand-Array verfolgen.

ngOnInit() { 
this.foreigners = []; 
this.foreignParamNames = []; 
this.fields = this.param.Fields; 
this.paramService.getParameterData(this.parameterName) 
       .then(
        data => this.processData(data), 
        error => {console.log(error)}); 

var foren = this.fields.filter(a=> a.DataType == 'FOREIGNKEYLIST'); 
for(var i = 0; i< foren.length; i++) 
{ 
    this.foreignParamNames.push(foren[i].DisplayName); 
    this.foreigners.push([]); 
} 

for(var j =0; j< foren.length; j++) 
{ 
    var that = this; 
    var ogfield = foren[j]; 
    //get foreign field data 
    this.paramService.getParameterData(foren[j].ForeignParameter) 
       .then(
        foreignRows => { 
         var values : StringKeyValuePair[] 
         values =[]; 
         for(var i=0; i<foreignRows.length; i++) 
         { 
          var foreignFields = foreignRows[i].ParameterData; 
          var sk = new StringKeyValuePair(); 
          for(var j =0; j<foreignFields.length; j++) 
          { 
           if(foreignFields[j].Name=="Id") 
           { 
            sk.Key = foreignFields[j].Value; 
           } 
           if(foreignFields[j].Name==ogfield.ForeignField) 
           { 
            sk.Value = foreignFields[j].Value; 
           }   
          } 
          values.push(sk); 
         } 
         var ii = that.foreignParamNames.indexOf(ogfield.DisplayName); 
         if(ii>=0) 
         { 
          that.foreigners[ii]=(values); 
         } 
        }, 
        error => {console.log(error)}); 
    } 
} 

und dann schließlich die getCellData Verfahren muss nicht mehr aus dem Dienst holen, sondern können nun aus der multidimensionalen Array für die Daten abrufen. Hier ist der Code.

getCellData(field: ParamField, fields : ParameterRowFieldContract[]) : 
string 
{ 
    for(var i=0; i<fields.length; i++) 
    {   
     if(fields[i].Name==field.DisplayName) 
     { 

      if(field.DataType == "FOREIGNKEYLIST") 
      { 
       //getforeign key value to display     
       var ii = this.foreignParamNames.indexOf(field.DisplayName); 

       var foreignfields= <StringKeyValuePair[]>this.foreigners[ii]; 

       for(var k=0; k<foreignfields.length; k++) 
       { 
        if(foreignfields[k].Key===fields[i].Value) 
        { 
         return foreignfields[k].Value; 
        } 
       } 

      } 
      else 
      {    
       return fields[i].Value; 
      } 
     }  
    } 
    return "N/A"; 
    } 

Der Code der HTML-Vorlage bleibt unverändert. Ich hoffe, dass dies jemand anderem helfen kann, der es braucht. Dies ist mehr wie eine Alternative von meiner ursprünglichen Linie des Denkens, aber wenn jemand eine bessere Möglichkeit hat, es zu tun, wenden Sie sich bitte