【问题标题】:How to apply filters to *ngFor Roles in Angular7如何在 Angular7 中将过滤器应用于 *ngFor 角色
【发布时间】:2019-10-28 04:00:43
【问题描述】:

目前,我正在为学校开发一个使用 Angular-7 作为前端的 Web 应用程序项目。我在复选框上显示用户角色,您可以选择多个角色。 我有以下用户角色

  1. 教师、2.学生、3.家长、4.管理员、5.超级管理员

角色检查服务

import { Injectable } from '@angular/core';
import { TokenService } from './token.service';

@Injectable({
  providedIn: 'root'
})
export class RolesCheckService {

  isAdmin = false;
  isStudent = false;
  isTeacher = false;
  isParent = false;
  isSuperAdmin = false;

  constructor(private token : TokenService) {
    if(this.token.checkRole('Admin')) {
      this.isAdmin = true;
    }
    if(this.token.checkRole('Student')) {
      this.isStudent = true;
    }
    if(this.token.checkRole('Teacher')) {
      this.isTeacher = true;
    }
    if(this.token.checkRole('Parent')) {
      this.isParent = true;
    }
    if(this.token.checkRole('SuperAdmin')) {
      this.isSuperAdmin = true;
    }
  }
}

user.component.ts

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ApiService } from '../../../shared/services/api.service';
import { SnotifyService } from 'ng-snotify';
import { Router, ActivatedRoute } from '@angular/router';
import { TokenService } from '../../../shared/services/token.service';
import { RolesCheckService } from 'src/app/shared/services/roles-check.service';

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.scss']
})
export class UsersComponent implements OnInit {

users = null;     //Store Users Data
roles = null;     //Store all roles Data
clients = null;

public error = {
  'role' : null,
  'email' : null,
  'client_id' : null,
  'first_name' : null,
  'last_name' : null,
  'password' : null
};

role = null;
User = 'User';

data = {          //User Update Data
 "id" : null,
 "first_name" : null,
 "last_name" : null,
 "client_id" : null,
 "role" : []
}

form = {         //New User add Data
  'first_name' : null,
  'last_name' : null,
  'email' : null,
  'client_id' : null,
  'password' : null,
  'password_confirmation' : null,
  'role' : []
}

headers = {     //Token for API Authorization
  'Authorization' : this.token.get(),
  'X-Requested-With' : 'XMLHttpRequest'
}

isSuperAdmin = false;

constructor(private roleManage : RolesCheckService , private route : ActivatedRoute, private pg:   NgbPaginationConfig, private token : TokenService, private http : HttpClient, private router :   Router,private api : ApiService, private notify : SnotifyService) {
 pg.boundaryLinks = true;
 pg.rotate = true;
}

ngOnInit() {
  console.log('isSuperAdmin: ' + this.roleManage.isSuperAdmin);
  this.isSuperAdmin = this.roleManage.isSuperAdmin;
  if(!this.isSuperAdmin){
    this.notify.error("Permission Denied");
    this.router.navigateByUrl("/home");
  }
  this.route.queryParams.subscribe(params => {
    if(params['role']){
      this.role = params['role'];
      this.User = this.role;

  } else {
    this.User = 'User';
    this.role = '';
  }
})
this.notify.clear();
this.notify.info("Loading...", {timeout: 0});

if(this.keyword) {
  this.api.get('users?search=' + this.keyword + '&page=' + this.pagination.page + '&sort=' + this.sortData.col + '&order=' + this.sortData.order + '&role=' + this.role, this.headers).subscribe(
    data => this.datahandler(data),
    error => { this.notify.clear(); console.log(error); this.notify.error(error.error.message); }
  );
} else {
  this.api.get('users?page=' + this.pagination.page + '&sort=' + this.sortData.col + '&order=' + this.sortData.order + '&role=' + this.role, this.headers).subscribe(
    data => this.datahandler(data),
    error => { console.log(error); this.notify.error(error.error.message); }
  );
}
this.api.get('role', this.headers).subscribe(
  data => { console.log(data); this.roles=data; },
  error => { console.log(error); this.notify.clear(); this.notify.error(error.error.message); }
);
this.api.get('users/clientall', this.headers).subscribe(
  data => this.clients = data,
  error => { this.notify.error(error.error.message) }
);
}


datahandler(data){
 console.log(data.data);
 this.notify.clear();
 this.users = data.data;
 this.pagination.max = data.total;
}

//New User add Handling
add(){
  this.notify.clear();
  this.form.first_name = null;
  this.form.last_name = null;
  this.form.email = null;
  this.form.password = null;
  this.form.password_confirmation = null;
  this.form.role = [];

  var modal = document.getElementById('addModal');
  modal.style.display = "block";
}

checkboxAdd(event){
  if(event.srcElement.checked){
  this.form.role.push(event.srcElement.name);
} else {
  var index =this.form.role.indexOf(event.srcElement.name);
  this.form.role.splice(index, index+1);
}
  console.log(this.form.role);
}

addModalSubmit(){
  this.notify.clear();
  this.notify.info("Wait...", {timeout: 0});
  this.api.post('users', this.form, this.headers).subscribe(
    data => {
      this.notify.clear();
      this.notify.info("User Added Successfully", {timeout: 2000});
      this.ngOnInit();
      this.closeAddModal();
   },
     error => { this.notify.clear(); this.error = error.error.errors; }
  );
 }

closeAddModal(){
 this.error = {
  'role' : null,
  'email' : null,
  'client_id' : null,
  'first_name' : null,
  'last_name' : null,
  'password' : null
};
  var modal = document.getElementById('addModal');
  modal.style.display = "none";
 }
}

user.component.html

<div class="col-xs-4">
  <a (click)='add()' class="btn btn-block btn-success" style="margin-right: 15px;"><i class="fa fa-plus"></i> Add New {{ User }}</a>
</div>
   <div id="addModal" class="modal" style="background-color: rgb(0,0,0); background-color: rgba(0,0,0,0.4);">
      <div class="modal-dialog" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h5 class="modal-title">Add New {{ User }}</h5>
          <button type="button" class="close" (click)='closeAddModal()'>
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
          <form #editUserForm=ngForm>
              <div class="form-group">
                <label for="name">First Name</label>
                <input type="name" name="first_name" id="inputName" class="form-control" placeholder="First Name" [(ngModel)]="form.first_name" required>
              </div>
              <div class="form-group">
                  <label for="name">Last Name</label>
                  <input type="name" name="last_name" id="inputName" class="form-control" placeholder="Last Name" [(ngModel)]="form.last_name" required>
                </div>
              <div class="form-group">
                  <label for="name">Email</label>
                  <input type="email" name="email" id="inputEmail" class="form-control" placeholder="example@email.com" required [(ngModel)]="form.email">
                </div>
                <div class="form-group">
                    <label for="name">Role</label>
                    <div *ngFor="let role of roles">
                        <input type="checkbox" name="{{ role.name }}" value="{{ role.name }}" (change)="checkboxAdd($event)"> {{ role.name }}
                    </div>
                </div>
          </form>

        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-primary" (click)='addModalSubmit()' [disabled]="!editUserForm.valid">Save changes</button>
          <button type="button" class="btn btn-secondary" (click)='closeAddModal()'>Close</button>
        </div>
      </div>
    </div>
</div>

我想从这里修改代码,

<div *ngFor="let role of roles">
    <input type="checkbox" name="{{ role.name }}" value="{{ role.name }}" (change)="checkboxAdd($event)"> {{ role.name }}
  </div>
  1. 如果登录用户为教师,则显示的角色应为:教师和学生

  2. 如果登录用户是管理员,它应该显示所有角色

  3. 如果登录用户是Student,应该显示:Student

我如何做到这一点?

【问题讨论】:

  • 您需要在角色中进行过滤。基于 users.name this roles.filter( role => { if (user.name === teacher) { return role.name === 'teacher' | | role.name === 'student' }});

标签: angular


【解决方案1】:

我建议在您从后端收到角色列表后立即过滤它们。所以你必须更改以下代码:

ngOnInit {
  // ...
  this.api.get('role', this.headers).subscribe(
    data => { console.log(data); this.roles=data; },
    error => { 
      console.log(error); this.notify.clear(); 
      this.notify.error(error.error.message);
    }
  );
  // ...
}

您需要添加一些过滤功能,将data 分配给this.rules

类似:

ngOnInit {
  // ...
  this.api.get('role', this.headers).subscribe(
    data => { console.log(data); this.roles=this.filterFn(data); },
    error => { 
      console.log(error); this.notify.clear(); 
      this.notify.error(error.error.message);
    }
  );
  // ...
}

filterFn(rolesList) { // returns filtered roles list
  // detect what roles should be applied.
}

如何检测。我没有看到你的完整代码,但我认为 RolesCheckService 可以完成这项工作,所以你可以使用它。

你也可以走 rxjs 的方式。您可以定义一些 observable,例如 appliedRoles$

代码是:

roles$ = new Subject();
appliedRoles$ = roles$
  .pipe(
    map(this.filterFn) // map operator have to be imported as `import { map } from 'rxjs/operators';
  );

ngOnInit {
  // ...
  this.api.get('role', this.headers).subscribe(
    data => { this.roles$.next(data); },
    error => { /** **/ }
  );
  // ...
}

您将在 html 中使用它,例如:

<!-- -->
<div *ngFor="let role of appliedRoles$ | async">
  <input type="checkbox" name="{{ role.name }}" value="{{ role.name }}" (change)="checkboxAdd($event)"> {{ role.name }}
</div>
<!-- -->

不要忘记将CommonModule 添加到组件模块的导入块中。 AsyncPipeCommonModule 的一部分,来自 @angular/common

您也可以避免使用 AsyncPipe。您必须将应用的角色放在一些变量中,如下所示:

ngOnInit() {
  // don't forget to unsubscribe (!!!)
  this.appliedRoles$.subscribe(appliedRoles => {
    this.appliedRoles = appliedRoles;
    // if you will use ChangeDetectionStrategy.OnPush strategy, you have to do `markForCheck` there (it is a method of ChangeDetectorRef)
  });
}

不要忘记在组件的 html 中使用新变量 appliedRoles

【讨论】:

    【解决方案2】:

    我认为实现您想要的最佳方式是为角色创建指令。 同样在您的 RolesCheckService 中,您应该创建当前角色的私有主题和该主题的公共可观察对象。因此,在您的指令中,您订阅了角色的 observable。您将所有逻辑都放入指令中。

    在指令中,您可以访问当前角色并检查它是否与用户角色匹配。

    这里是similar directive you want to achieve的指南。

    一旦您编写了指令,就可以说您将其命名为 *canAccess。您只需将其添加到 ngFor 的输入中即可。

    <div *ngFor="let role of roles">
        <input *canAcess="role.name" type="checkbox" name="{{ role.name }}" value="{{ role.name }}" (change)="checkboxAdd($event)"> {{ role.name }}
      </div>
    

    这将在指令中传递角色名称。

    希望这会有所帮助!查看指南了解更多信息。

    【讨论】:

      猜你喜欢
      • 2019-09-08
      • 2019-07-16
      • 2018-02-26
      • 2014-04-05
      • 1970-01-01
      • 2020-11-18
      • 2011-07-06
      相关资源
      最近更新 更多