2017-08-26 13 views
0

私はangular2で作業しています。ある親コンポーネントから別の子コンポーネントにデータを渡しています。angg2でngOnChange()が2回働いていません

<app-datatable-repr [myFilterData]="filterData"></app-datatable-repr> 

filterDataはオブジェクトです。

最初のOnChangesは"filterData"の変更を検出しますが、2回目はngChangeが"filterData"の変更を検出しません。

この問題を解決するにはどうすればよいですか?

HAR-ファイルupload.component.ts

import { Component, OnInit } from '@angular/core'; 
import { HarFileServiceService } from '../har-file-service.service'; 

@Component({ 
    selector: 'app-har-file-upload', 
    templateUrl: './har-file-upload.component.html', 
    styleUrls: ['./har-file-upload.component.css'] 
}) 

export class HarFileUploadComponent implements OnInit { 

    constructor(private harFileServiceService:HarFileServiceService) { } 

    ngOnInit() { 
    } 
    filterData:Object = {}; 
    changeListener(event:any){ 
    var that = this; 
    var file = event.target.files[0]; 
    var myReader = new FileReader(); 
    var harFile = this.harFileServiceService; 
    myReader.onload = function(e:any){ 
     var jsonData = JSON.parse(e.target.result); 
     harFile.render(jsonData); 
     that.filterData = harFile.responseFileData; 
     // console.log(that.filterData) 
    } 
    // console.log(file); 
    myReader.readAsText(file); 
    } 
} 

HAR-ファイルservice.service.ts

import { Injectable } from '@angular/core'; 
import * as $ from 'jquery'; 

@Injectable() 
export class HarFileServiceService { 
    constructor() { } 
    log:Object = { entries: {} }; 
    totals:Object = {}; 
    pads:Object = {}; 
    left; 
    right; 
    idctr:number = 0; 
    reqCount:number = 0; 
    totalReqSize:number = 0; 
    totalRespSize:number = 0; 
    requestObj:Object = {'resources':[]}; 
    responseFileData:any = {}; 
    render(har: any) { 
     var pageref; 
     var that = this; 
     $.each(har.log.entries, function (index, entries) { 
      console.log(index, entries); 
      var singleReqOb = {}; 
      that.requestObj['resources'].push(singleReqOb); 
      pageref = pageref || entries.pageref; 
      if(entries.pageref === pageref) { 
       that.entry(index, entries); 
      } 
     }); 
     this.responseFileData = this.requestObj; 
     console.log(this.responseFileData); 
    } 
    entry(id:any, entry:any) { 
     id = id || this.idctr++; 
     this.log['entries'][id] = entry; 
     var t = new Date(entry.startedDateTime).getTime(); 
     if(this.left && this.right) { 
      this.left = (this.left < t) ? this.left : t; 
      this.right = (this.right > t) ? this.right : t; 
     } 
     else { 
      this.left = this.right = t; 
     } 
     if(entry.request) { 
      this.request(id, entry.request); 
     } 
     if(entry.response) { 
      this.response(id, entry.response); 
     } 
    } 
    request(id:any, request:any) { 
     if(this.log['entries'][id]) { 
      this.log['entries'][id].request = request; 
     } 
     else { 
      this.log['entries'][id] = { 
       id: id, 
       request: request 
      }; 
     } 
     this._updateRequest(id, request); 
     this.reqCount = this.reqCount + 1; 
     if(request.headersSize && request.headersSize > 0) { 
      this.totalReqSize = this.totalReqSize + request.headersSize; 
     } 
     if(request.bodySize && request.bodySize > 0) { 
      this.totalReqSize = this.totalReqSize + request.bodySize; 
     } 
    } 
    response(id:any, response:any) { 
     if(this.log['entries'][id]) { 
      this.log['entries'][id].response = response; 
      this._updateResponse(id, response); 

      if(response.headersSize && response.headersSize > 0) { 
       this.totalRespSize = this.totalRespSize + response.headersSize; 
      } 
      if(response.bodySize && response.bodySize > 0) { 
       this.totalRespSize = this.totalRespSize + response.bodySize; 
      } 
     } 
     else { 
     } 
    } 
    _updateRequest(id:any, request:any) { 
     var reqObj = this.requestObj['resources'][id]; 
     if(request.url) { 
      reqObj['filePath'] = request.url; 
     } 
    }; 
    _updateResponse(id:any, response:any) { 
     var reqObj = this.requestObj['resources'][id]; 
     var type = response.content.mimeType; 
     var type_0 = type.split("/")[0]; 
     var type_1 = type.split("/")[1]; 
     switch (type_1) { 
      case "javascript": 
      case "x-javascript": 
       reqObj['type'] = 'script'; 
       break; 
      case "css": 
      case "json": 
      case "html":  
       reqObj['type'] = type_1; 
       break; 
      case "x-shockwave-flash": 
       reqObj['type'] = 'flash'; 
       break; 
      default: 
       reqObj['type'] = type; 
       break; 
     } 
     if(type_0 == 'image' || type_0 == 'video'){ 
      reqObj['type'] = type_0; 
      reqObj['type'] = (reqObj['type'] == 'image') ? 'image' : reqObj['type']; 
     } 
     if(response.content && response.content.text) { 
      reqObj['size'] = response.bodySize; 
     }else{ 
      reqObj['size'] = ''; 
     } 
    } 
} 

ngOnChangeここ

import { Component, OnInit , OnChanges, SimpleChanges, Input} from '@angular/core'; 
import * as $ from 'jquery'; 
import 'datatables.net' 
import { HarFileServiceService } from '../har-file-service.service'; 

@Component({ 
    selector: 'app-datatable-repr', 
    templateUrl: './datatable-repr.component.html', 
    styleUrls: ['./datatable-repr.component.css'] 
}) 
export class DatatableReprComponent implements OnInit, OnChanges { 
    @Input() myFilterData; 
    constructor(private harFileServiceService:HarFileServiceService) { } 
    public tableWidget: any; 
    ngOnInit() { 
    this.initDatatable(); 
    } 

    ngOnChanges(changes:SimpleChanges){ 
    if(changes.myFilterData.currentValue.hasOwnProperty('resources')){ 
     this.tableWidget.clear().draw(); 
     this.tableWidget.rows.add(changes.myFilterData.currentValue.resources); // Add new data 
     this.tableWidget.columns.adjust().draw(); // Redraw the DataTable 
    } 
    } 
    private truncate(string:any, len:any){ 
    if (string.length > len) 
     return string.substring(0,len)+'...'; 
    else 
     return string; 
    }; 
    parseURL(url:any) { 
     var parsed_url:any = {} 
     if (url == null || url.length == 0) return parsed_url; 
    var protocol_i = url.indexOf('://'); 
    parsed_url.protocol = url.substr(0, protocol_i); 
     var remaining_url = url.substr(protocol_i + 3, url.length); 
     var domain_i = remaining_url.indexOf('/'); 
     domain_i = domain_i == -1 ? remaining_url.length - 1 : domain_i; 
     parsed_url.domain = remaining_url.substr(0, domain_i); 
     parsed_url.path = domain_i == -1 || domain_i + 1 == remaining_url.length ? 
      null : remaining_url.substr(domain_i + 1, remaining_url.length); 
     var domain_parts = parsed_url.domain.split('.'); 
     switch (domain_parts.length) { 
      case 2: 
       parsed_url.subdomain = null; 
       parsed_url.host = domain_parts[0]; 
       parsed_url.tld = domain_parts[1]; 
       break; 
      case 3: 
       parsed_url.subdomain = domain_parts[0]; 
       parsed_url.host = domain_parts[1]; 
       parsed_url.tld = domain_parts[2]; 
       break; 
      case 4: 
       parsed_url.subdomain = domain_parts[0]; 
       parsed_url.host = domain_parts[1]; 
       parsed_url.tld = domain_parts[2] + '.' + domain_parts[3]; 
       break; 
     } 
     parsed_url.parent_domain = parsed_url.host + '.' + parsed_url.tld; 
     return parsed_url; 
    } 
    imgExt:any = ["png", "gif", "jpeg", "jpg"] 
    vidExt:any = ["mov", "flv", "mpg", "mpeg", "mp4", "ogv", "webm"] 
    private initDatatable(): void { 
    var myData = this.myFilterData.hasOwnProperty('responseFileData') ? this.myFilterData.hasOwnProperty('responseFileData') : {}; 
    var that = this; 
    let exampleId: any = $('#resourcesListing'); 
    this.tableWidget = exampleId.DataTable({ 
     aLengthMenu : [], 
      aaData: myData, 
      bPaginate: false, 
      bAutoWidth: false, 
      order: [], 
      language: { 
       search: "Search Resources : ", 
       lengthMenu: "Display _MENU_ Resources", 
       infoFiltered: "(filtered from _MAX_ Resources)", 
       info: "Showing _START_ to _END_ of _TOTAL_ Resources", 
       infoEmpty: "", 
       zeroRecords: "<div style='padding: 10px;'>No resources match your search criteria.</div>", 
       emptyTable: "<div style='padding: 10px;'>No resources available.</div>", 
       paginate: { 
        first: " <i class='fa fa-fast-backward'></i> ", 
        previous: " <i class='fa fa-backward'></i> ", 
        next: " <i class='fa fa-forward'></i> ", 
        last: " <i class='fa fa-fast-forward'></i> " 
       } 
      }, 
     aoColumns: [ 
       { 
        mDataProp: 'filePath', 
        mRender: function (data, type, full) { 
      var urlinfo = (that.parseURL(data));; 
         return that.truncate(urlinfo.domain, 50); 
        }, 
        sWidth: "200px" 
       }, 
       { 
        mDataProp: 'filePath', 
        mRender: function (data, type, full) { 
      var urlinfo = (that.parseURL(data)); 
         return "<a target='_blank' href='"+data+"'/>" + that.truncate(urlinfo.path ? urlinfo.path.split("?")[0] : "", 60) + "</a>"; 
      }, 
      sWidth: "400px" 
       }, 
       // { 
       // mData: "filePath", 
       // mRender: function (data, type, full) { 
       //  return '<a href="#" class="info"><i class="fa fa-info" aria-hidden="true"></i></a>'; 
       // }, 
       // sWidth: "60px", 
       // sClass: "center" 
       // }, 
       { 
        mData: "type", 
        sWidth: "100px", 
        mRender: function (data, type, full) { 
         var resType = data, 
          resPath = full['filePath']; 
         if(resType == "css"){ 
          // background-url will have type css, change to bg-img 
          var ext = resPath.split('.').pop(); 
          if(that.imgExt.indexOf(ext) >= 0){ 
           // showResType = "bg-img"; 
           resType = "bg-image"; 
          } 
         }else if(resType == "other" || resType == ""){ 
          // video comes as type 'other' in firefox and empty in chrome 
          var ext = resPath.split('.').pop(); 
          if(that.vidExt.indexOf(ext) >= 0){ 
           // showResType = "video"; 
           resType = "video"; 
          } 
         }else if(resType == "img"){ 
          resType = "image"; 
         } 
         return resType; 
        } 
       }, 
       { 
        mDataProp: 'filePath', 
        mRender: function (data, type, full) { 
         return (full.type == "image" || full.type == "img") ? '<div class="imageBackgroundParent"><div class="imageBackground" style="background-image: url('+ data +');"></div></div>' : ""; 
        }, 
        sWidth: "120px", 
        sClass: "center" 
       }, 
       { 
        mData: "size", 
        sWidth: "80px" 
       } 
      ], 
    }); 
    } 
} 

れるsampleData

"resources":[ 
    { 
    "filePath": "http://www.cricbuzz.com/live-cricket-scores/18460/sl-vs-ind-2nd-test-india-tour-of-sri-lanka-2017", 
    "type": "html", 
    "size": 119362 
    }, 
    { 
    "filePath": "http://gc.kis.v2.scr.kaspersky-labs.com/EAA2612E-9291-A04E-A659-D0B272EEC835/main.js", 
    "type": "script", 
    "size": 104685 
    }, 
    { 
    "filePath": "http://i.cricketcb.com/statics/site/images/cbz-logo.png", 
    "type": "image", 
    "size": 0 
    } 
] 
+0

あなたは 'filterData'内部に専用のプロパティを更新するを変更するlodashcloneDeepを使うのか? – Aravind

+0

@Aravindの質問にコードを追加しました。 – Kallis

+0

「ngOnChanges」と言うと、変更検出器が変更を検出していないことを意味しますか? BcどこにでもngOnChangesメソッドを使用しているのがわかりません。 – diopside

答えて

2

オブジェクトがngOnChange(変更可能なので)と呼ばれていません。 これは、ngOnChange()が引数インスタンスが変更されたときにのみ起動されたため(ngOnChange()はそのプロパティの1つではない)発生します。

それは何のことができますhere

に不変オブジェクトを利用するには約あなたがより多くを読むことができます。つまり、オブジェクトを変更することはできません。 immutable.js by facebookという素晴らしい図書館があります。

Object.assign()も使用できます。それを使用すると、(参照を変更する代わりに)オブジェクトの新しいインスタンスを作成しています。だから、長い話を短くするために、

constructor(private harFileServiceService:HarFileServiceService) { } 

    ngOnInit() { 
    } 
    filterData:Object = {}; 
    changeListener(event:any){ 
    var file = event.target.files[0]; 
    var myReader = new FileReader(); 
    var harFile = this.harFileServiceService; 
    myReader.onload = (e:any)=>{ 
     var jsonData = JSON.parse(e.target.result); 
     harFile.render(jsonData); 
     this.filterData = Object.assign({},harFile.responseFileData); 
    } 
    // console.log(file); 
    myReader.readAsText(file); 
    } 
} 

は、上記の例では、私はObject.assignを使用しました()。また、私は少し構文を変更してuse'd ecmascript arrow functionを変更しました。

1

代わりに参照

this.filterData = _.cloneDeep(harFile.responseFileData); 
+0

あなたは@Aravindをチェックします – Kallis

+0

@aravindはあなたの答えを少し説明してくれますか? –

+0

@PardeepJain' object.assign'を使用しているときに、onChangesがそのオブジェクトの参照を変更します – Aravind

関連する問題