typescript PrimeNG 下拉选择项数据绑定

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/38228013/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 03:37:51  来源:igfitidea点击:

PrimeNG dropdown selected item data binding

typescriptangularprimeng

提问by BrianRT

I am simply trying to bind data from a dropdown menu with ngModel. There is an error I receive when the app loads that makes some sense.

我只是想从下拉菜单中绑定数据ngModel。当应用程序加载时,我收到了一个有意义的错误。

browser_adapter.js:84 EXCEPTION: No value accessor for ''

This leads me to believe that the error is stemming from the fact that ngModelis not initially bound with any data when the app loads.

这使我相信该错误源于ngModel应用程序加载时最初未绑定任何数据的事实。

I'm not the best at using Observables... so beware.

我不是最擅长使用 Observables 的……所以要小心。

Partial of the html dropdown

部分 html 下拉菜单

<p-dropdown [options]="actionsToTake" (onChange)="onToggleCreateActionInput()" 
  [(ngModel)]="action"></p-dropdown>

Relevant TypeScript (excluded imports)

相关的 TypeScript(排除进口)

export class ActionView {
  public actionsToTake: SelectItem[] = [];
  public action: Action = new Action();

  constructor (private actionCreateService: ActionCreateService) {
    // populate dropdown list (actionsToTake) with data from service call
    this.actionCreateService.getActionFields().subscribe((resp) => {
      for (let i = 0; i < resp.data.data.actionElm.length; i++) {
        this.actionsToTake.push({label: resp.data.data.actionElm[i].name,
          value: resp.data.data.actionElm[i].name});
      }
    });
  }

  public onToggleCreateActionInput = (action): void => {
    // test if something in "action" exists, and then do something based on that
  };
}

So, when the app initially loads, actionis empty. I would expect that an empty value bound to ngModelwouldn't break the app, but maybe I am misinterpreting the error. Ultimately I want the selected item to be bound, and I think getting past this error will get me to that point.

因此,当应用程序最初加载时,它action是空的。我希望绑定到的空值ngModel不会破坏应用程序,但也许我误解了错误。最终,我希望绑定选定的项目,我认为克服这个错误将使我达到这一点。

采纳答案by BrianRT

It turns out I was somewhere in the middle between using the deprecated Angular forms and the new Angular forms. To use PrimeNG, upgrade to the new forms and include this in your application's bootstrap:

事实证明,我介于使用已弃用的 Angular 形式和新的 Angular 形式之间。要使用 PrimeNG,请升级到新表单并将其包含在应用程序的引导程序中:

import {disableDeprecatedForms, provideForms} from '@angular/forms';

bootstrap(App, [
  disableDeprecatedForms(),
  provideForms()
]);

Then, in my parent component where I instantiate the form, I had to change the imports from:

然后,在我实例化表单的父组件中,我必须更改导入:

import {NgForm, FORM_DIRECTIVES, CORE_DIRECTIVES} from '@angular/common';

to

import {NgForm, FORM_DIRECTIVES, NgModel} from '@angular/forms';
import {CORE_DIRECTIVES} from '@angular/common';

In the child component, these imports aren't needed. You need to include [ngModelOptions]="{standalone: true}"wherever [(ngModel)]is. So, in my case:

在子组件中,不需要这些导入。你需要包括[ngModelOptions]="{standalone: true}"任何地方[(ngModel)]。所以,就我而言:

<p-dropdown [(ngModel)]="actions" [ngModelOptions]="{standalone: true}"></p-dropdown>

回答by Daniel Pliscki

I haven't test it yet, but from what I've read it seems that you'll have to update your app to use the new forms and disable the old deprecated version.

我还没有测试它,但从我读过的内容来看,您似乎必须更新您的应用程序才能使用新表单并禁用旧的弃用版本。

import {bootstrap} from '@angular/platform-browser-dynamic';
import {provide} from '@angular/core';
import {AppComponent} from './app.component'
import {disableDeprecatedForms, provideForms} from '@angular/forms';

bootstrap(AppComponent, [
  disableDeprecatedForms(),
  provideForms(),
]);

Related resources https://github.com/primefaces/primeng/issues/549#issuecomment-230305403

相关资源 https://github.com/primefaces/primeng/issues/549#issuecomment-230305403

http://forum.primefaces.org/viewtopic.php?f=35&t=46115&p=144059&hilit=no+value+accessor+for#p144059

http://forum.primefaces.org/viewtopic.php?f=35&t=46115&p=144059&hilit=no+value+accessor+for#p144059

EDIT!

编辑!

For nested components you'll have to implement a Control Value Accessor inside the child component in order to allow the parent component to take control over it. I have an example where I implement a custom toggle component, but this component also uses prime ng toggle component.

对于嵌套组件,您必须在子组件内实现一个控制值访问器,以允许父组件对其进行控制。我有一个例子,我实现了一个自定义切换组件,但这个组件也使用了主要的 ng 切换组件。

This is how the child component looks like:

这是子组件的样子:

import {Component,Input, Provider, forwardRef} from '@angular/core'
import {ControlValueAccessor, NG_VALUE_ACCESSOR, CORE_DIRECTIVES} from '@angular/common';

import {ToggleButton} from 'primeng/primeng'

const noop = () => {};

const CUSTOM_VALUE_ACCESSOR = new Provider(
    NG_VALUE_ACCESSOR, {
        useExisting: forwardRef(() => CustomToggle),
        multi: true
    });

@Component({
    selector: 'custom-toggle',
    template: `<span>
                  <p-toggleButton
                     [(ngModel)]="value"   >
                  </p-toggleButton>
               </span>`,
    directives: [CORE_DIRECTIVES,ToggleButton],
    providers: [CUSTOM_VALUE_ACCESSOR]
})

export class CustomToggle implements ControlValueAccessor {           
           
    private _value: string;
    
    private _onTouchedCallback: (_:any) => void = noop;
    private _onChangeCallback: (_:any) => void = noop;
    
    get value(): any { return this._value};
    
    set value(v: any) {
        if (v !== this._value) {
            this._value = v;
            this._onChangeCallback(v);
        }
    }
    
    onTouched() {
        this._onChangeCallback;
    }
    
    writeValue(value: any) {
        this._value = value;
    }
    
    registerOnChange(fn: any) {
        this._onChangeCallback = fn;
    }
    
    registerOnTouched(fn: any) {
        this._onTouchedCallback = fn;
    }
    
}

And this is how it can be used inside parent components

这就是它可以在父组件中使用的方式

<custom-toggle [(ngModel)]="myToggle"  ></custom-toggle>

Where myToggle is just a boolean variable.

其中 myToggle 只是一个布尔变量。

More on how to implement a control value accessor: http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel

有关如何实现控制值访问器的更多信息:http: //almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel