简体   繁体   中英

Angular Spread Operator not working properly?

I am trying to process an array in angular. I need to get admin user name from an array and trying below approach

export class AppComponent  {
  adminName = ''
  data = {
    id:1,
    name:'Test User One',
    users:[
      {id:1,name:'User 2',role:'Management Admin'},
      {id:2,name:'User 3',role:'User'},
      {id:3,name:'User 1',role:'Profile Admin'},
    ]
  }

  ngOnInit(){
     this.getAdminName(this.data.users)
  }

  getAdminName(users){
   let name = ''
    name = users.filter((user)=>{
      user.role = user.role.replace(/\s/g, '-').toUpperCase()
      return user.role === 'PROFILE-ADMIN'
    }).map(row=>{
      return row.name
    })
    this.adminName = name[0]
  }
}

This is working and i am able to get adminName but it also changes role of data object and converts object like this

{
  "id": 1,
  "name": "Test User One",
  "users": [
    {
      "id": 1,
      "name": "User 2",
      "role": "MANAGEMENT-ADMIN"
    },
    {
      "id": 2,
      "name": "User 3",
      "role": "USER"
    },
    {
      "id": 3,
      "name": "User 1",
      "role": "PROFILE-ADMIN"
    }
  ]
}

I understand why this happened and i tried using spread operator but it is not working i tried below approach

Approach one

this.getAdminName([...this.data.users]) // passing from here using spread operator

Approach Second

getAdminName(users){
   let usersList = [...users]
   let name = ''
    name = usersList.filter((user)=>{
      user.role = user.role.replace(/\s/g, '-').toUpperCase()
      return user.role === 'PROFILE-ADMIN'
    }).map(row=>{
      return row.name
    })
    this.adminName = name[0]
  }

I am able to do it like below

getAdminName(users){
   let name = ''
   let role;
    name = users.filter((user)=>{
      role = user.role //used a variable in which holds 
      role = role.replace(/\s/g, '-').toUpperCase()
      return role === 'PROFILE-ADMIN'
    }).map(row=>{
      return row.name
    })
    this.adminName = name[0]
  }

But I want to do it using spread Operator approach so Please suggest me where i am going wrong

Stackblitz link is here

https://stackblitz.com/edit/angular-rjnytr

I would change filter logic to avoid any side effects.

getAdminName(users) {
  const name = users
    .filter(user => user.role.replace(/\s/g, '-').toUpperCase() === 'PROFILE-ADMIN')
    .map(row => row.name);

  return name ? name[0] : '';
}

This way you do not need to think about how spread operator works.

this.getAdminName(this.data.users) 

users is a reference type. So you need to create a deep copy of an object. Try to use JSON.parse method to create a deep copy of an object:

let usersList = [...JSON.parse(JSON.stringify(users))]

In your function, replace the user.role = user.role.replace(/\s/g, '-').toUpperCase() by a new variable, this:

getAdminName(users){
   let usersList = [...users]
   let name = ''
    name = usersList.filter((user)=>{
      let role = user.role;
      role = role.replace(/\s/g, '-').toUpperCase()
      return role === 'PROFILE-ADMIN'
    }).map(row=>{
      return row.name
    })
    this.adminName = name[0]
  }

First of all, Spread operation won't work,

Reason, it's only helpful for single layered data structure, meaning array of primitive data types, for array of objects it dose not create deep copy when nested properties are in picture.

So you should use Lodashs cloneDeep method.

UPDATED

install lodash in your angular project

Then import it like

import { cloneDeep } from 'lodash'; Blockquote

and use it like,

  getAdminName(users){
   let usersList = cloneDeep(users);
   let name = ''
    name = usersList.filter((user)=>{
      user.role = user.role.replace(/\s/g, '-').toUpperCase()
      return user.role === 'PROFILE-ADMIN'
    }).map(row=>{
      return row.name
    })
    this.adminName = name[0]
  }

This should solve your problem here

The spread operator on the array do just that spreads the array. In the way you are using it you are simply passing an equivalent amount of arguments to the getAdmin() method or the userList variable as the elements in the array.

Try something like this:

ngOnInit(){
 this.getAdminName(this.data.users)
}

getAdminName(users){
   const adminUser = users.find(({ role }) => {
     role = role.replace(/\s/g, '-').toUpperCase()
     return role === 'PROFILE-ADMIN'
   });
   this.adminName = adminUser.name;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM