当前位置: 首页 > 知识库问答 >
问题:

如何用ngRx存储在表中编辑行或创建行

司空健
2023-03-14

我是angular的新手,我正在尝试用ngRx集成angular项目和curd操作,但在创建或编辑行时面临问题。我在这里附上我的代码。

用户-management.component.html

<div>
  <div class="row m-auto px-2">
    <div class="col d-flex justify-content-end">
      <button class="btn btn-outline-secondary btn-sm" (click)="addNew()">
        <i class="fas fa-plus"></i>
        Add Single User
      </button>
      <button class="btn btn-outline-secondary btn-sm ml-1" (click)="onClick(input)">
        <i class="fas fa-cloud-upload-alt"><input type="file" class="mx-auto" style="display: none"
            (change)="onFileUpload($event)" #input /></i>
        Upload User File
      </button>
    </div>
  </div>
  <div class="row m-auto px-2">
    <div class="col form-inline">
      <form>
      <input placeholder="Filter By FirstName" type="text" class="advancedSearchTextbox" />
      <input placeholder="Filter By PhoneNumber" type="text" class="advancedSearchTextbox" />
      <select class="advancedSearchTextbox" required >
        <option value=""  selected hidden>Filter By Role</option>
        <option value="Center-in-Charge">Center-in-Charge</option>
        <option value="Field-Auditor">Field-Auditor</option>
        <option value="Client Sponser">Client Sponser</option>
      </select>
      <button type="reset" class="btn btn-outline-secondary btn-sm">Reset</button>
    </form>
    </div>
  </div>
  <div class="row clearfix mx-auto mt-3">
    <div class="mx-auto" style="overflow: auto; width: 80vw; height: 65vh">
      <table class="table">
        <thead style="font-size: span">
          <tr class="text-center border border-left-0 border-right-0 border-top-0">
            <th class="text-center">Select</th>
            <th class="text-center">First Name</th>
            <th class="text-center">Last Name</th>
            <th class="text-center">Phone</th>
            <th class="text-center">EmailId</th>
            <th class="text-center">Role</th>
            <th class="text-center">Actions</th>
            <th class="text-center">Active/Deactive</th>
          </tr>
        </thead>
        <tbody>
      
          <tr *ngFor="let user of users$| async ; let i = index"
            class="text-center border border-left-0 border-right-0 border-top-0">
            <td class="text-center"><input type="checkbox" /></td>
            <td class="p-1">
              <input type="text" [(ngModel)]="user.firstName" [disabled]="!(enableEdit && enableEditIndex == i)"
                class="form-control form-control-sm text-center select-width" />
            </td>
            <td class="p-1">
              <input type="text" [(ngModel)]="user.lastName" [disabled]="!(enableEdit && enableEditIndex == i)"
                class="form-control form-control-sm text-center select-width" />
            </td>
            <td class="p-1">
              <input type="text" [(ngModel)]="user.phone" [disabled]="!(enableEdit && enableEditIndex == i)"
                class="form-control form-control-sm text-center select-width" />
            </td>
            <td class="p-1">
              <input type="text" [(ngModel)]="user.email" [disabled]="!(enableEdit && enableEditIndex == i)"
                class="form-control form-control-sm text-center select-width" />
            </td>
            <td class="p-1">
              <input type="text" [(ngModel)]="user.role" [disabled]="!(enableEdit && enableEditIndex == i)"
                class="form-control form-control-sm text-center select-width" />
            </td>
            <td class="p-1">
              <button *ngIf="isNew && enableEdit && enableEditIndex == i" class="btn page-secondary-action-btn"
                (click)="cancel(i)">
                <i class="fa fa-times"></i>
              </button>
              <button *ngIf="enableEdit && enableEditIndex == i" id="saveBtn" class="btn page-primary-action-btn"
                (click)="saveSegment(user)" type="submit">
                <i class="fas fa-save"></i>
              </button>
              <i class="fas fa-user-edit mx-2" *ngIf="!(enableEdit && enableEditIndex == i)"
                (click)="enableEditMethod(i)"></i>
              <i (click)="deleteFieldValue(field.userId,i)" class="fa fa-trash ml-2" aria-hidden="true"></i>
            </td>
            <td class="p-1">
              <label class="switch"><input type="checkbox" id="togBtn" />
                <div class="slider round">
                  <span class="on">Active</span><span class="off">Deactive</span>
                </div>
              </label>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
  </div>

  <div class="modal fade" id="addMultipleUser" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle"
    aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered" role="document">
      <div class="modal-content">
        <div class="modal-header">
          <h4 class="modal-title" id="exampleModalLongTitle">
            Please Upload a file to create multiple user
          </h4>
          <button type="button" class="close" data-dismiss="modal" aria-label="Close">
            <span aria-hidden="true">&times;</span>
          </button>
        </div>
        <div class="modal-body">
          <input type="file" id="myFile" name="filename" accept=".xls,.xlsx" />
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-secondary" data-dismiss="modal">
            Close
          </button>
          <button type="button" class="btn btn-primary">Uplaod</button>
        </div>
      </div>
    </div>
  </div>
</div>
<router-outlet></router-outlet>

用户-management.component.ts

import { tap } from 'rxjs/operators';
import { getUserByIndex } from './../../../../store/selectors/user.selectors';
import { ListUserStarts, AddEmptyRow, DeleteUserStart, AddUserStarts } from './../../../../store/actions/user.action';
import { User } from './../../../../store/models/user';
import { FormArray } from '@angular/forms';
import { Component, OnInit, ElementRef } from '@angular/core';
import { Router } from '@angular/router';
import { Store, select } from '@ngrx/store';
import { AppState } from '../../../../store';
import { Observable } from 'rxjs';
import { loadUsers } from '../../../../store/selectors/user.selectors';

@Component({
  selector: 'app-user-access-management',
  templateUrl: './user-access-management.component.html',
  styleUrls: ['./user-access-management.component.css', './user-access-management.component.scss']
})
export class UserAccessManagementComponent implements OnInit {

  users$: Observable<User[]>;
  targetUser$: Observable<User>;
  responseOfDelet$: Observable<string>;

  fileName = "";
  newDynamic$: Observable<User[]>;
  enableEdit = false;
  enableEditIndex = null;
  disableButton: boolean = false;
  isOld: boolean = true;
  OldUser: any = {};
  isNew: boolean = true;
  showFilter = false;
  searchBy = null;
  searchString = "";


  constructor(private router: Router, private store: Store<AppState>) { }

  ngOnInit(): void {
    console.log("inside ngOnIt");
    this.store.dispatch(new ListUserStarts());
    this.users$ = this.store.pipe(select(loadUsers)).pipe(
      tap(result => console.log(result))
    );

  }

  addFilter() {
    this.showFilter = true

  }
  removeFilter() {
    this.showFilter = false
    this.searchBy = ""
  }
  modifyFilter(event: Event) {
    console.log("event ", event);
    this.searchBy = ((event.target) as HTMLInputElement).value
  }

  show_hide() {
    console.log("on click");
    var click = document.getElementById("dropdown-list");
    console.log(click);
    if (click.style.display === "none")
      click.style.display = "block";
    else
      click.style.display = "none";
  }

  callModifyComp() {
    console.log("inside callModifyComp()");
    this.router.navigate(['user-access-management/modifyUser'])
  }

  enableEditMethod(i, name) {
    this.isNew = true;
    this.enableEdit = true;
    this.enableEditIndex = i;
    // this.OldUser = { ...this.user$[i] };
    console.log("", this.OldUser);
  }
  addNew() {
    this.isNew = false;


    this.store.dispatch(new AddEmptyRow({
      firstName: "",
      lastName: "",
      phone: "",
      email: "",
      role: "",
      userId: "",
      selected: false
    }));
    this.enableEdit = true;
    this.enableEditIndex = 0;
    

  }

  onClick(val) {
    (val as HTMLInputElement).click()
    console.log(val as HTMLInputElement);
  }

  saveSegment(field, index) {
    console.log(field);
    // if (!this.isNew) {
    // this.enableEdit = false;
    // this.disableButton = false;
    // this.store.dispatch(new AddUserStarts({
    //   firstName:field.firstName,
    //   lastName: field.lastName,
    //   phone: field.phone,
    //   email:field.email,
    //   role: field.role
    // }))

  }

  edit(field, index) {
    console.log("inside edit", index)
    this.enableEdit = false;
    this.disableButton = false;
    this.isNew = false;
  }

  cancel(i) {
    this.enableEdit = false;
  }

  onFileUpload(event) {
    const fileRef = event.target.value as string
    this.fileName = (event.target.value as string).slice(12, fileRef.length)
  }

  deleteFieldValue(userId) {
    this.store.dispatch(new DeleteUserStart({
      userId: userId
    }));

  }

}

User.Action.ts

import { createAction, props } from "@ngrx/store";
import { Action } from '@ngrx/store';
import { User } from "../models/user";

export enum UserActions {
  ListUserStarts = "[user] List User Starts",
  ListUserFinished = "[user] List User Finished",

  AddUserStarts = "[user] Add Usser Starts",
  AddUserEnds = "[user] Add USer ends",
  AddEmptyRow ="[user] Add row",
  AddEmptyRowEnds ="[user] Add row ends" ,

  DeleteUserStarts = "[user] Delete User Starts",
DeleteUserEnds = "[user] Delete User Ends",

}

export interface UserPayloadType {

  firstName: string,
  lastName: string,
  phone: string,
  email: string,
  role:string
}

 export interface DeleteResponse{
   message: string,
   status: string
 }

export class AddUserStarts implements Action {
  readonly type = UserActions.AddUserStarts;
  constructor(public payload: UserPayloadType) {}
}

export class AddUserEnds implements Action {
  readonly type = UserActions.AddUserEnds;
  constructor(public payload: {status:string}) {}
}

export class AddEmptyRow implements Action {
  readonly type = UserActions.AddEmptyRow;
  constructor(public payload: User) {}
}

export class AddEmptyRowEnds implements Action {
  readonly type = UserActions.AddEmptyRowEnds;
  constructor(public payload: User[]) {}
}

export class DeleteUserStart implements Action {
  readonly type = UserActions.DeleteUserStarts;
  constructor(public payload: { userId: string }) {}
}

export class DeleteUserEnds implements Action {
  readonly type = UserActions.DeleteUserEnds;
  constructor(public payload: {status:string;}) {}
}

export class ListUserStarts implements Action {
  readonly type = UserActions.ListUserStarts;
}
export class ListUsersFinished implements Action {
  readonly type = UserActions.ListUserFinished;

  constructor(public payload: User[]) {

  }
}

export type UserActionTypes =
  ListUserStarts
  | ListUsersFinished
  | AddUserStarts
  | AddUserEnds
  | DeleteUserStart
  | DeleteUserEnds
  |AddEmptyRow;

User.Reducer.ts

import { UserActions, UserActionTypes } from './../actions/user.action';
import { createReducer, on, State, Action } from "@ngrx/store";
import { User } from "../models/user";

export interface UserState {
  users: User[];
}

const initialState: UserState = {
  users: null,
};

export function userReducer(state: UserState = initialState, action: UserActionTypes
): UserState {
  console.log(action.type);
  switch (action.type) {
    case UserActions.ListUserFinished: {
      return {
        ...state,
        users: action.payload,
      };
    }
    case UserActions.AddEmptyRow: {
      return {
        ...state,
        users: [action.payload,...state.users],
      };
    }
    case UserActions.AddUserEnds:
      const usersCopy = state.users.concat()
      usersCopy.push(action.payload)
      return {
        ...state,
        users: usersCopy

      };
    default:
      return state;
  }
}

User.effects.ts

import { ListUserStarts, UserActionTypes, UserActions, ListUsersFinished, AddUserStarts, AddUserEnds, AddEmptyRow, AddEmptyRowEnds, DeleteUserStart, DeleteUserEnds, DeleteResponse } from './../actions/user.action';
import { User } from './../models/user';
import { Injectable } from "@angular/core";
import { Actions, ofType, Effect } from "@ngrx/effects";
import { userJwtToken } from '../selectors/auth.selectors';
import { select, Store } from "@ngrx/store";
import { switchMap, tap, map } from "rxjs/operators";
import { HttpClient, HttpResponse } from "@angular/common/http";

import { Observable, of } from "rxjs";
import { AppState } from "..";
import { UserUrl } from "./URLs";

export interface FetchAllUser {
    firstName: string,
    lastName: string,
    phone: string,
    email: string,
    role: string,
    userId: string
}

@Injectable()
export class UserEffects {
    jwtToken: string;
    id: string[] = [];
    constructor(
        private actions$: Actions,
        private http: HttpClient,
        private store: Store<AppState>,
    ) {
        console.log("inside effects of users");
    }

    @Effect({ dispatch: false })
    addUserStart = this.actions$.pipe(
        ofType<AddUserStarts>(UserActions.AddUserStarts),
        switchMap((user) => {
            this.store.pipe(select(userJwtToken)).subscribe(jwtToken => {
                this.jwtToken = jwtToken;
            });

            const option = {
                headers: {
                    jwtToken: this.jwtToken
                }
            }

            return this.http

                .post('http://localhost:8080/gradingTool/user/createSingleUser',user.payload, option)
                .pipe(
                    tap((data) => {
                        console.log(data);
                    }),
                    map((response) => {
                       return new AddUserEnds(new User(
                        user.payload.firstName,
                        user.payload.lastName,
                        user.payload.phone,
                        user.payload.email,
                        user.payload.role,
                        "",
                        false
                        )); 
                    })
                );
        })
    );
}

User.Selectors.ts

import { createSelector, createFeatureSelector } from "@ngrx/store";
import { AppState } from "..";

const userState = (state: AppState) => state.user;

export const loadUsers = createSelector(
  userState,
  (state) => state.users
);

export const getUserByIndex = createSelector(
  userState,
  (state, props) => {
    return state.users[props.userIndex];
  }
);

索引。ts

import { ActionReducerMap } from '@ngrx/store';
import { userReducer, UserState } from './reducers/user.reducer';

export interface AppState {
  user: UserState;
}

export const appReducer: ActionReducerMap<AppState> = {
  user: userReducer
};

当我单击add sinle user按钮时,我能够向表中添加新行,但当我开始向该行添加值时,我面临以下问题:错误类型错误:无法在UserAccessManagementComponent_tr_50_Template_input_ngModelChange_4_listener(user-access-management.component.html:77)上将对象“[object object]”的只读属性“first name”赋值。编辑选项也会发生同样的情况

共有1个答案

甄伟兆
2023-03-14

你能写出console.log里面的内容吗:

this.users$ = this.store.pipe(select(loadUsers)).pipe(
  tap(result => console.log(result))
);

给你点小费,有个速记:

this.users$ = this.store.pipe(select(loadUsers)).pipe(
  tap(console.log)
);
 类似资料:
  • 我的数据库中有几个存储过程,结构如下: 我被要求在每个有它的过程中用另一个子句替换中的表。 我经过了很多研究,但我应该创建一个自己工作的脚本,我还没有找到合适的东西。例如,我找到了显示存储过程源代码的,但是有没有办法将其放入变量中以便编辑它?

  • 问题内容: 在联结表中进行编辑的最佳实践是什么? 现在我在一间商店里有30件物品。我想编辑该列表,然后取消选中10个项目,然后选中50个新项目。 我通过以下方式执行此操作:通过“ ItemId”从“ ItemsInShops”中删除所有行,并添加新值。我认为这不是很好的解决方案。有没有更好的方法来进行这种更新? 也许我没有以身作则表达问题。看看这个: 用户可以具有任意数量的角色。 那是联结表“ U

  • 问题内容: 我有一个存储过程,该过程将通过复制旧表的结构来创建新表。但是在创建新表之前,我需要检查该表是否存在,如果存在,则需要先删除该表。这是我的存储过程。 但是,如果该表存在,我总是会收到类似以下的错误。哪里错了? 问题答案: 让我感到难过…在这种情况下,“如果存在”似乎无法与exec配合使用。更新了以下脚本:

  • 我在stackoverflow上看到过类似的问题,但无论如何,我无法用这些答案解决我的问题。 我想做的是: 单击JTable中的double on单元格(由于IsCelledTable方法,该单元格可以编辑) 在自定义表中保存单元格的新值以打印此新值 更新我的数据库(SQlite)中的数据 这是我的自定义表模型 . 这是我打印JTable的JPanel:

  • 我有两个组件Display.jsx和DisplayList.jsx。组件协同工作以显示本地存储中的值。问题在于DisplayList.JSX handleEdit()方法切片。 Github项目 我的想法: 我在这个论坛上问如何删除本地存储值,得到了这个答案,没有解释:堆栈溢出问题 它可以工作,但现在我需要做类似的切片来编辑旧的存储值并用新的存储值替换。但是我不知道怎么做。 总结:在方法handl

  • 我是Vue.js的新手。我正在创建一个应用程序,其中我使用Vuetify和nuxt,并希望有一个可重用的编辑器模式。到目前为止,我发现我可以使用V-Dialog。我有一个宠物列表,我想要一个编辑器,该宠物弹出时,单击编辑操作链接每行。编辑器应该从后端加载pet对象并显示编辑器表单。当点击模式中的Save按钮时,宠物应该被保存并通知家长,以便它可以更新列表。我希望能够添加宠物在另一个页面(例如在一个

  • 我正在寻找一些关于使用模型在django admin上创建一个“仅创建”字段的解决方案。我以前看到过一些问题,但没有人能回答核心问题:当用户在管理面板上创建时,字段应该出现,但我不希望能够编辑。 models.py admin.py “readonly_fields”解决了以后编辑时的问题,但在创建时却导致了禁止。 问题:我使用这个字段来做一个散列,我不想再做这个改变…我曾想过使用第二个字段,在创

  • 为了解决MySql中的问题,即某些语句只允许在我试图创建的存储过程中运行,然后在JdbcTem板提交的sql中删除存储过程。一个简单的例子是(这恰好是在Spring引导中): cript.sql在哪里 在mySql workbench中运行它可以很好地工作,但是由JdbcTemplate提交时会出现错误 据我所知,这是因为JdbcTemplate不允许使用那些