【问题标题】:"[(ngModel)]" weird issue after a subscribe using apollo, not updating使用阿波罗订阅后的“[(ngModel)]”奇怪问题,不更新
【发布时间】:2018-05-28 01:11:33
【问题描述】:

我对 [(ngModel)] 有一个奇怪的问题。我开始使用 Angular 5,并且我已经创建了一个带有输入的表单并且它可以工作。为了连接到数据库,我使用 Apollo 发送 GraphQL 查询和突变。基本上我正在做一个简单的设置页面,可以创建、删除和编辑设置。创建和删除设置就像一个魅力,在编辑设置表单中我遇到了麻烦。我做了与创建表单完全相同的事情,然后在 ngOnInit() 中进行查询并将其添加到包含所有输入内容的变量中。当我加载表单时,我可以看到表单中的值,但是当我编辑它们时,ngModel 没有更新。

我有一个叫做设置的界面

export interface Setting {
    id?: number;
    ...
    active: boolean;
    name: string;
}

这是我的组件的一部分:

@Component({
    selector: 'app-settings-edit',
    templateUrl: './settings-edit.component.html',
    styleUrls: ['./settings-edit.component.css']
})
export class SettingsEditComponent implements OnInit {

    conf: Setting = {
        ...
        active: false,
        name: null
    };

    constructor(private apollo: Apollo,
                private router: Router,
                private route: ActivatedRoute) { }

    ngOnInit() {
        let id = this.route.snapshot.paramMap.get('id');
        this.getConf(id);
    }

    getConf(id){
        this.apollo.watchQuery<any>({
            query: GET_CONF,
            variables:{
                id: id
            }
        }).valueChanges.subscribe(({data})=>{

            this.conf = data.getConfiguration;

        })
    }

    updateConf(form: NgForm) {
        if(form.valid){
            this.apollo.mutate({
                mutation: UPDATE_CONF,
                refetchQueries: [{
                    query: ALL_SETTINGS_QUERY
                }],
                variables: {
                    id: this.conf.id,
                    ...
                    active: this.conf.active,
                    name: this.conf.name
                }
            }).subscribe(({data}) => {
                this.router.navigate(["/settings"]);
            })
        }

    }

    ...

}

这是我的 html 的一部分:

<div class="row">
  <div class="col-md-6">
    <label>Name:</label>
    <div class="form-group" [ngClass]="{'has-error has-feedback': hasErrors(name)}">
      <input type="text" name="name" class="form-control border-input" placeholder="Configuration Name" [(ngModel)]="conf.name"
        #name="ngModel" required>
      <span *ngIf="hasErrors(name)" class="fa fa-remove form-control-feedback"></span>
    </div>
  </div>
  <div class="col-md-3">
    <label>Activate?:</label>
    <div class="form-group">
      <mat-slide-toggle [(ngModel)]="conf.active" name="active"></mat-slide-toggle>
    </div>
  </div>
</div>

这是我面临的问题的 GIF:

现在我确实注意到了一些我觉得很奇怪的东西:

如果我把这段代码改成这个(我知道丑),它就可以工作:

this.apollo.watchQuery<any>({
  query: GET_CONF,
  variables:{
      id: id
  }
}).valueChanges.subscribe(({data})=>{
  // If I change this line from:
  // this.conf = data.getConfiguration;
  // to
  this.conf = <Setting>JSON.parse(JSON.stringify(data.getConfiguration));
})

我把它换成了this.conf = &lt;Setting&gt;JSON.parse(JSON.stringify(data.getConfiguration));

我从 Apollo 得到的内容是 JSON 字符串化并再次解析。它有效..

这里:

为什么会发生这种情况?它与打字稿有关吗?还是角?感谢您的帮助。

【问题讨论】:

  • 你能把你绑定的东西展示给你的桌子吗?

标签: angular apollo


【解决方案1】:

你能试试下面的代码吗?它可能有效。我也遇到了同样的问题。

<input type="text" name="name" class="form-control border-input" 
placeholder="Configuration Name" [ngModel]="conf.name" 
(onModelChange)="changeConfigurationName($event)" #name="ngModel" required>

changeConfigurationName(event) {
    this.conf.name = event;
}

【讨论】:

  • 嗨@pratik-gadoya,感谢您的建议,我在我的表单中尝试了这个,但没有成功。事件没有触发。我在里面放了一个console.log,没有任何东西发送到控制台。
【解决方案2】:

最近在尝试使用 ngModel 编辑来自 Apollo 的回复时,我自己也遇到了这个问题。这个问题实际上是由于 Apollo 冻结了响应对象 (link),因此您必须复制对象才能对其进行编辑。这就是为什么将 JSON 转换为字符串并再次返回的原因。或者,您可以使用扩展运算符来复制它(或Object.assign)。

this.apollo.watchQuery<any>({
  query: GET_CONF,
  variables:{
      id: id
  }
}).valueChanges.subscribe(({ data }) => {
  this.conf = {...data.getConfiguration};
})

请注意,Object.assign 和扩展运算符仅创建浅拷贝。如果您有一个包含嵌套对象的对象,那么您将使用 lodash 之类的东西来执行深层复制。

【讨论】:

    猜你喜欢
    • 2017-12-11
    • 2020-09-26
    • 1970-01-01
    • 2019-06-04
    • 2021-01-05
    • 2019-12-06
    • 2021-02-13
    • 2021-07-13
    • 2017-03-03
    相关资源
    最近更新 更多