最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular 2 not updating until any object is clicked - Stack Overflow

programmeradmin1浏览0评论

The following is something I'm trying to get working based on the Angular Tutorial.

export class DashboardComponent implements OnInit {
      title = 'Current Robots';
      private sobots: Robot[];

      constructor(
        private router: Router,
        private sobotService: RobotService) { 
      }

      getRobots() { 
          this.sobotService.getRobots().then(sobots => Array.prototype.push.apply(this.sobots, sobots.data));     
      }

      ngOnInit() {
          this.getRobots();
      }

      gotoDetail(sobot: Robot) {
        let link = ['/detail', sobot.Id];
        this.router.navigate(link);
      }

And the View

<h3>{{title}}</h3>
<div class="grid grid-pad">        
  <div *ngFor="let sobot of sobots" (click)="gotoDetail(sobot)" class="col-1-4">
    <div class="module sobot">
      <p>HostKey</p>
      <h4>{{sobot.HostKey}}</h4>
    </div>
  </div>
</div>
<sobot-search></sobot-search>

sobots.data looks to be returning the data object as expected - however it's still not updating until I click on any button/route/any event is fired.

No errors show up in the console and I'm quite confused!

I've gone ahead and tried to ensure that it's only adding data to the original array object but even that doesn't seem to work!

The following is something I'm trying to get working based on the Angular Tutorial.

export class DashboardComponent implements OnInit {
      title = 'Current Robots';
      private sobots: Robot[];

      constructor(
        private router: Router,
        private sobotService: RobotService) { 
      }

      getRobots() { 
          this.sobotService.getRobots().then(sobots => Array.prototype.push.apply(this.sobots, sobots.data));     
      }

      ngOnInit() {
          this.getRobots();
      }

      gotoDetail(sobot: Robot) {
        let link = ['/detail', sobot.Id];
        this.router.navigate(link);
      }

And the View

<h3>{{title}}</h3>
<div class="grid grid-pad">        
  <div *ngFor="let sobot of sobots" (click)="gotoDetail(sobot)" class="col-1-4">
    <div class="module sobot">
      <p>HostKey</p>
      <h4>{{sobot.HostKey}}</h4>
    </div>
  </div>
</div>
<sobot-search></sobot-search>

sobots.data looks to be returning the data object as expected - however it's still not updating until I click on any button/route/any event is fired.

No errors show up in the console and I'm quite confused!

I've gone ahead and tried to ensure that it's only adding data to the original array object but even that doesn't seem to work!

Share Improve this question asked Aug 17, 2016 at 4:49 NathanNathan 6637 silver badges12 bronze badges
Add a comment  | 

5 Answers 5

Reset to default 8

So it turns out that the sobotService was returning a q.js promise and not an ES6 promise. I believe this is probably why it didn't update as I'd expect it to like it did in the Heroes Tutorial.

By forcing it to update in the zone eg:

  this.sobotService .getRobots().then(ODataRobots => {
      this.zone.run(() => this.sobots = ODataRobots.data);          
  });

It managed to update the view as soon as the promise resolved.

I'll probably have to figure out if there is an easy way to remove the q.js promise from the library I am using (o.js) but in the meantime this works as expected!

Solution

As Abdul waheed mentioned before, the code that modifies the state needs to be wrapped with the ngZone service:

  // `ngZone` is the instance of the `NgZone` service.
  this.ngZone.run(() => {
    this.myState = 'new value';
  });

But as Madhur Bhaiya pointed out it is not detailed enough, so here I'm explaining a bit more.

Larger example

This example is provided by José Pedro Silva at GitHub Angular issues page.

public constructor(private ngZone: NgZone) {
}

public async update() {
  try {
    this.viewVariable = null;
    let newValue = await this.dataService.getAsync();

    this.ngZone.run(() => {
      this.viewVariable = newValue;
    });
  }
  catch (error) {
    this.viewVariable = error;
  }
}

Explanation

When there's an Asynchronous code (outside Angular scope) modifying the State, it will not trigger a View update. The click will do it. The NgZone Service can fix this issue.

The technique is helpful for AJAX calls as well as for any asynchronous call, such as an external library callback (which was my case).

Try assigning an initial value to this.sobots.

export class DashboardComponent implements OnInit {
      title = 'Current Robots';
      private sobots: Robot[] = []; <---- this

      constructor(
        private router: Router,
        private sobotService: RobotService) { 
      }

      getRobots() { 
          this.sobotService.getRobots().then(sobots => Array.prototype.push.apply(this.sobots, sobots.data));     
      }

      ngOnInit() {
          this.getRobots();
      }

      gotoDetail(sobot: Robot) {
        let link = ['/detail', sobot.Id];
        this.router.navigate(link);
      }
}

Otherwise you're trying to push to a null object and I don't think push.apply will work for that. In nodejs:

> let x
undefined
> x
undefined
> Array.prototype.push.apply(x,['y','z'])
TypeError: Array.prototype.push called on null or undefined
    at repl:1:22
    at REPLServer.defaultEval (repl.js:272:27)
    at bound (domain.js:280:14)
    at REPLServer.runBound [as eval] (domain.js:293:12)
    at REPLServer.<anonymous> (repl.js:441:10)
    at emitOne (events.js:96:13)
    at REPLServer.emit (events.js:188:7)
    at REPLServer.Interface._onLine (readline.js:224:10)
    at REPLServer.Interface._line (readline.js:566:8)
    at REPLServer.Interface._ttyWrite (readline.js:843:14)

this helped me.

this.someService.captureDetails(data).subscribe((res) => {
  this.zone.run(() => { 
   this.data = res ;
    }
  });
});

In my case The problem was due to changeDetection: ChangeDetectionStrategy.OnPush in the app component.

Removed changeDetection: ChangeDetectionStrategy.OnPush from app component and its working fine.

发布评论

评论列表(0)

  1. 暂无评论