ngFor is not updating List values in realtime in Angular
Asked Answered
G

1

6

I have added a component in a parent component. Child component gets data from server and shows it in a modal. Problem is that it is not updating data in realtime.

Here is html of child component:

<!--Permission MODAL-->
<div class="modal fade" id="transactionPermissionModal" role="dialog">
  <div class="modal-dialog">

    <!-- Modal content-->
    <div class="modal-content">
      <div class="modal-body">
        <p class="text-center">Create New</p>


          <div *ngFor="let permittedProfile of assignedPermissions" class="row">
            <div class="col-12">
              <p class="myText float-left">{{permittedProfile.profile.email}}({{permittedProfile.permission_type}})</p>
              <span style="float: right; cursor: pointer" (click)="RemovePermissionToUser(permittedProfile.profile.email)">&times;</span>
            </div>
          </div>

        <div class="row">
          <div class="col-7" style="padding-right: 0px;">
            <input type="text" style="border-right: none" class="new-transaction-textfield" placeholder="Invite Someone" id="permission-email">
          </div>
          <div class="col-3" style="padding-left: 0px;padding-right: 0px;">
            <select id="permission-dropdown" style="background-color: transparent; height: 32px; border: 1px solid #d9d9d9;border-left: none; outline: none">
              <option value="edit">can edit</option>
              <option value="view">can view</option>
            </select>
          </div>
          <div class="col-2" style="padding-left: 0px;">
            <button type="button" class="btn invite-btn" (click)="GivePermissionToUser()">Invite</button>
          </div>
        </div>

        <br />

      </div>
      <!--<div class="modal-footer">-->
      <button type="button" id="permission-modal-close-btn" data-dismiss="modal" style="display: none">Close</button>
      <!--</div>-->
    </div>

  </div>
</div>

here is that specific function which gets data and save it so that it should be visible on UI in realtime because of data binding

/**
   * Get permission list from server
   *
   * @param nextLink: link to retrieve a specific page/result_set
   * @param childIndex: index number if user has clicked any child of a transaction otherwise it 'll be null
   */
  GetPermissionsList(nextLink, childIndex: number = null) {

    if (nextLink === '') {
      this.assignedPermissions = [];
    }
    console.log(this.assignedPermissions);

    this.transactionsService.HandlePermissionRequestGeneracially(
      {}, this.url + nextLink, 'GET'
    ).subscribe((response) => {

      for (const entry of response.results) {
        this.assignedPermissions.push(entry);
      }

      this.shouldPermissionsVisible = true;
      console.log(this.assignedPermissions);

      const next = response.next;
      if (next !== null) {
        this.GetPermissionsList(next.substring(next.indexOf('?'), next.length), childIndex);
        return;
      }
    }, (error) => {
      this.snackbarHandler.showSnackBar('Error while getting permission');
    });
  }

Its getting correct data from server but problem is that it doesn't update it on UI right away. When first time it opens modal it shows no data but second time it shows result of first time. It means that it shows only old data saved not the one which it has retrieved from server.

I am calling GetPermissionList function like this:

const myThis = this;
    $('#transactionPermissionModal').on('shown.bs.modal', function (e) {
      myThis.GetPermissionsList('');
    });
Greisen answered 6/5, 2019 at 10:45 Comment(8)
Can you please post the results of your console.log calls? Are you sure your function is called twice?Meantime
@Mic yes its showing correct data in results of console.log.....empty list in first answer and list with all entries, which retrieved from server, in second answerGreisen
@ZohabAli why you are not using async to archive this? :)Milwaukee
@YashRami I am trying your solution right now. I ll let you knowGreisen
Then it should work. It means that the myThis trick does not work and you are not modifying the right member variable. Why do you use that instead of regular Angular events?Meantime
@Mic I want to call this function only when modal popups. That is why I am using it, and its calling function at right timeGreisen
@Mic actually you are right. If I dont call function from within Jquery function then it shows data as expected. If you write this as answer then I can accept itGreisen
Yes, and I pointed to the underlying javascript reason in my answer. You should prefer Angular event: start this callback on the (click) or whatever event, and you don't have to worry about that.Meantime
M
3

First, you should use Angular events instead of a query selector. Is there a good reason why you can't?

Second, as you say the console.log calls work correctly, it means that the member variable assignedPermissions is actually not modified in the correct object.

Which points to the real issue: the myThis thing does not work because the context of the call is not the right one in the callback. And it leads you to this kind of issue: How to access the correct `this` inside a callback?

Following this reasoning, here is the correct way to set your callback (which is, I repeat, not the Angular-way of doing):

$('#transactionPermissionModal').on('shown.bs.modal', (function (e) {
  this.GetPermissionsList('');
}).bind(this));

or

$('#transactionPermissionModal').on('shown.bs.modal', e => this.GetPermissionsList(''));
Meantime answered 6/5, 2019 at 11:46 Comment(2)
Genius! Thanks for all the help. You are right that I should use Angular events. Although jquery methods are not working right now for me which you have suggested. So I am gonna try some other way. But thanks for helping me find the problem :)Greisen
@Mic Great Answer :)Milwaukee

© 2022 - 2024 — McMap. All rights reserved.