Angular 13 - 数据可在组件内部访问,但未显示在 html 页面上

Posted

技术标签:

【中文标题】Angular 13 - 数据可在组件内部访问,但未显示在 html 页面上【英文标题】:Angular 13 - Data is accessible inside component, but does not show on the html page 【发布时间】:2022-01-24 06:26:44 【问题描述】:

所以,我现在正在学习 Angular,并尝试做一个 CRUD 应用程序。几乎一切正常,除了尝试使用 ID 获取数据时,我可以访问 component.ts 文件中的所有数据,但同样不会呈现到 html 文件中。这是我尝试过的:-

edit-to.component.ts

export class EditTodoComponent implements OnInit 

private tid: number = 0;

  public Todo:TodoModel= null ;
  public desc:string='';
  public title:string='';
  public id:number;

  constructor(private route: ActivatedRoute, private http:HttpClient)  

  ngOnInit(): void 
    this.route.paramMap.subscribe(all_params =>
      this.tid = parseInt(all_params.get('id'))
      //console.log( all_params.get('id'))
      //console.log( this.tid );
    );

    this.getTodoFromId(this.tid)


  

   getTodoFromId(id)
    //console.log("id="+id)
     this.http.get<data: any>('http://localhost:3000/api/todos/get_todo_from_id/'+id).subscribe((data) =>
      console.log("response in angular= \n");
      this.Todo = data[0]
      

      console.log(this.Todo.todo_title) //-> This one works


editOnSubmit(form:NgForm)
  //something here

edit-todo.component.html

 <div class="col-md-12">
    <form (ngSubmit)="editOnSubmit(todoForm)" #todoForm="ngForm">
      <input type="text" class="form-control" id="todo_id" [(ngModel)]="id" name="todo_id" value="1">
      <div class="mb-3">
        <label for="todo_title" class="form-label">Title</label>

        <input type="text" class="form-control" id="todo_title" [(ngModel)]="title" name="title" value=" Todo.todo_title">  //-> This one does not work.

      </div>
      <div class="mb-3">
        <label for="label" class="form-label">Description</label>
        <textarea  class="form-control" id="todo_description" [(ngModel)]="desc" name="desc" ></textarea>
      </div>

      <button type="submit" class="btn btn-success">Edit To Do</button>
    </form>
  </div>
</div>

分离出来,

来自 edit-to.component.ts :-

console.log(this.Todo.todo_title) 有效

但来自 edit-todo.component.html

&lt;input type="text" class="form-control" id="todo_title" [(ngModel)]="title" name="title" value=" Todo.todo_title"&gt; 不起作用

【问题讨论】:

【参考方案1】:

定义一个 BehaviorSubject 类型的属性。

isAvailableData = new BehaviorSubject<boolean>(true);

然后你订阅数据的地方设置为true。

getTodoFromId(id)
//console.log("id="+id)
 this.http.get<data: any>('http://localhost:3000/api/todos/get_todo_from_id/'+id).subscribe((data) =>
  console.log("response in angular= \n");
  this.Todo = data[0];

  this.isAvailableData.next(true);

  console.log(this.Todo.todo_title) //-> This one works

然后在你的 HTML 中添加 ngIf 到 col-md-12 div:

<div class="col-md-12" *ngIf="(isAvailableData | async)">
<form (ngSubmit)="editOnSubmit(todoForm)" #todoForm="ngForm">
  <input type="text" class="form-control" id="todo_id" [(ngModel)]="id" name="todo_id" value="1">
  <div class="mb-3">
    <label for="todo_title" class="form-label">Title</label>

    <input type="text" class="form-control" id="todo_title" [(ngModel)]="title" name="title" value=" Todo.todo_title">  //-> This one does not work.

  </div>
  <div class="mb-3">
    <label for="label" class="form-label">Description</label>
    <textarea  class="form-control" id="todo_description" [(ngModel)]="desc" name="desc" ></textarea>
  </div>

  <button type="submit" class="btn btn-success">Edit To Do</button>
</form>

另外,您在表单中犯了错误,输入应如下所示:

而且没有必要为 id、title、...定义一个属性 这些是 todo 对象的属性

 <label for="todo_title" class="form-label">Title</label>

  <input type="text" class="form-control" id="todo_title" [(ngModel)]="Todo.todo_title" name="todo_title" #todo_title="ngModel">

【讨论】:

我正在尝试不使用 Rxjs。 最佳实践是使用 Rxjs。你也可以使用布尔类型 public isAvailableData: boolean; 并将 ngIf 更改为:*ngIf="isAvailable"【参考方案2】:

这是因为您在同一输入字段上配置了一个 ngModel 和一个值

在这种情况下,ngModel 优先于 value 属性

要修复它,您可以在 ngOnInit 中初始化标题

this.title = this.Todo.todo_title; 

在您的情况下,您等待来自 http 请求的回复,因此在 hte http 回复之后进行初始化:

getTodoFromId(id)
     this.http.get<data: any>('http://localhost:3000/api/todos/get_todo_from_id/'+id).subscribe((data) =>
      console.log("response in angular= \n");
      this.Todo = data[0]
      this.title = this.Todo.todo_title;

      console.log(this.Todo.todo_title);


【讨论】:

让我试试这个。但是,您提出的方法,如果输入字段的数量更多,比如 20 个左右怎么办?有没有更好的方法? ngModel 可以是对象的属性。如果你有一个大结构,我建议你在模型对象中复制这个对象并在你的输入中使用它。获取 Todo 副本并分配 [(ngModel)] = todoCopy.todo_title 我尝试了这个方法,但是虽然我可以访问getTodoFromId() 中的数据,但我无法在ngOnInit 中访问它。当我尝试时,this.getTodoFromId(this.tid) console.log("Here"+this.Todo.todo_title)ngOnInit 内,它说 todo_title 不是 Todo 的已知属性 是的,您在 getTodoFromId 方法中有一个 http.get,因此您必须在 http 回复后设置数据 我做到了。但是,我无法访问 ngOnInit 或 html 页面中的数据

以上是关于Angular 13 - 数据可在组件内部访问,但未显示在 html 页面上的主要内容,如果未能解决你的问题,请参考以下文章

如何访问对象内部的数组?

从Angular中的父组件访问子ngIf

angular7构建一个navroute组件但不知道现在该做什么

Angular:使用 NgIf 删除组件、内部表单和元素?

Angular 新手,无法从组件外部访问变量

Angular Material 的设计之美