Javascript 如何使用“角度8”取消选择“选择元素”中的选定选项元素

Javascript 如何使用“角度8”取消选择“选择元素”中的选定选项元素,javascript,angular,typescript,angular-reactive-forms,Javascript,Angular,Typescript,Angular Reactive Forms,我有以下要求: 我为select元素mainSelect和subSelect找到了两个FormControl对象,它们是必需的 subSelect根据mainSelect中的值而变化 当main select更改为不包含subSelect中的值时subSelect需要变为无效,因此FormGroup两个FormControl的一部分也变为无效 但是如果包含subSelect中的值,则subSelect需要保留其实际值 (StackBlitz链接后面描述了一个具体示例。) 我的问题解决此要求:

我有以下要求:

  • 我为select元素
    mainSelect
    subSelect
    找到了两个
    FormControl
    对象,它们是
    必需的
  • subSelect
    根据
    mainSelect
    中的值而变化
  • main select
    更改为不包含
    subSelect
    中的值时
    subSelect
    需要变为
    无效
    ,因此
    FormGroup
    两个
    FormControl
    的一部分也变为
    无效
  • 但是如果包含
    subSelect
    中的值,则
    subSelect
    需要保留其实际值
(StackBlitz链接后面描述了一个具体示例。)

我的问题解决此要求:

如果
mainSelect
的值发生变化,并且
subSelect
的值未包含
subSelect
将取列表的第一个值,而不是变为
null
/
无效

因此,如果“subSelect”的选定值变为null,并且浏览器中未选择任何值,则解决方案将为

到目前为止我所尝试的:

我试图创建一个组件并实现
ControlValueAccessor
接口。我的问题似乎就在这里。我想我真的不明白这是怎么回事

我在上观看了以下视频并阅读了与
ControlValueAccessor
相关的文章(,),但仍然无法解决我的问题

这是我代码的一部分:

你也可以在网上找到它

示例

如果在浏览器中
MainSelect
具有值
thirdMainSelect
SubSelect
具有值
fifthSubSelect
MainSelect
将其值更改为
firstMainSelect
SubSelect
应无选择值

选择.component.ts

export class SomeObject {
  value: string;
  parameters: {[parameterName: string]: string} = {};
}

@Component({
  selector: "app-select",
  templateUrl: "./select.component.html",
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: SelectComponent,
    multi: true
  }]
})
export class SelectComponent implements ControlValueAccessor, OnChanges {
  @ViewChild("select", {static: true}) select: ElementRef;
  @Input() tableId: string;
  @Input() filter: { [parameterName: string]: string};

  returnedTable: SomeObject[];

  onChange: (_: any) => void;
  onTouched: () => void;

  selected: string;

  constructor(private tableService: TableService) { }

  loadTable(): void {
    this.tableService.getTable(this.tableId, this.filter)
      .subscribe(table => {
        this.returnedTable = table;
      });
  }

  ngOnChanges(): void {
    this.loadTable();
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  writeValue(value: string): void {
    this.selected = value;
  }
}
@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"]
})
export class AppComponent implements OnInit {

  form: FormGroup;
  containerObject: ContainerObject;

  selectedMainValue: string;

  constructor(private tableService: TableService,
              private formBuilder: FormBuilder) {

  }

  ngOnInit(): void {
    this.tableService.getContainerObject()
      .subscribe(containerObject => {
        this.containerObject = containerObject;
        this.selectedMainValue = containerObject.mainSelect;
        this.initForm();
      });
  }

  private initForm(): void {
    this.form = this.formBuilder.group({
      mainSelect: [this.containerObject.mainSelect, Validators.required],
      subSelect: [this.containerObject.subSelect, Validators.required]
    });
    this.subscribeToMainSelectChanged();
    this.subscribeToSubSelectChanged();
  }

  onSubmit(): void {
    if (this.form.valid) {
      this.containerObject.mainSelect = this.form.get("mainSelect").value;
      this.containerObject.subSelect = this.form.get("subSelect").value;
      this.tableService.saveContainerObject(this.containerObject);
    }
  }

  private subscribeToMainSelectChanged() {
    this.form.get("mainSelect").valueChanges
      .subscribe(mainSelect => {
        this.selectedMainValue = mainSelect;
        console.log(this.form.status);
      });
  }

  private subscribeToSubSelectChanged() {
    this.form.get("subSelect").valueChanges
      .subscribe(() => {
        console.log(this.form.status);
      });
  }
}
select.component.html

<select class="form-control" #select (change)="onChange($event.target.value)">
  <option *ngFor="let item of returnedTable" [value]="item.value" [selected]="selected === item.value">{{item.value}}</option>
</select>
<div>
  <form id="wrapper" [formGroup]="form" (ngSubmit)="onSubmit()">
    <div id="left" class="form-group row">
      <label for="mainSelect" class="col-form-label col-sm-2">MainSelect</label>
      <div class="col-sm-6">
        <app-select
          id="mainSelect"
          formControlName="mainSelect"
          [tableId]="'mainSelectTable'"
          [filter]="{firstType: 'firstParameter'}"
        ></app-select>
      </div>
    </div>
    <div id="right" class="form-group row">
      <label for="subSelect" class="col-form-label col-sm-2">SubSelect</label>
      <div class="col-sm-6">
        <app-select
          id="subSelect"
          formControlName="subSelect"
          [tableId]="'firstParameter'"
          [filter]="{firstType: 'firstParameter', secondType: selectedMainValue}"></app-select>
      </div>
    </div>
    <p></p>
    <button id="button" type="submit">Submit</button>
  </form>
</div>
app.component.html

<select class="form-control" #select (change)="onChange($event.target.value)">
  <option *ngFor="let item of returnedTable" [value]="item.value" [selected]="selected === item.value">{{item.value}}</option>
</select>
<div>
  <form id="wrapper" [formGroup]="form" (ngSubmit)="onSubmit()">
    <div id="left" class="form-group row">
      <label for="mainSelect" class="col-form-label col-sm-2">MainSelect</label>
      <div class="col-sm-6">
        <app-select
          id="mainSelect"
          formControlName="mainSelect"
          [tableId]="'mainSelectTable'"
          [filter]="{firstType: 'firstParameter'}"
        ></app-select>
      </div>
    </div>
    <div id="right" class="form-group row">
      <label for="subSelect" class="col-form-label col-sm-2">SubSelect</label>
      <div class="col-sm-6">
        <app-select
          id="subSelect"
          formControlName="subSelect"
          [tableId]="'firstParameter'"
          [filter]="{firstType: 'firstParameter', secondType: selectedMainValue}"></app-select>
      </div>
    </div>
    <p></p>
    <button id="button" type="submit">Submit</button>
  </form>
</div>

主选择
再选择

提交
我认为这只是使用价值观。如果有两个数组数据和子数据以及类似

form = new FormGroup({
    prop1: new FormControl(),
    prop2: new FormControl()
  });
简单的

this.form.get("prop1").valueChanges.subscribe(res => {
  this.dataService.getData(res).subscribe(data=>{
    this.subdata=data;
    if (!this.subdata.find(x=>x.value==this.form.get("prop2").value))
      this.form.get("prop2").setValue(null);
  }).unsubscribe()
});

必须足够了,请看

我认为这只是使用价值观。如果有两个数组数据和子数据以及类似

form = new FormGroup({
    prop1: new FormControl(),
    prop2: new FormControl()
  });
简单的

this.form.get("prop1").valueChanges.subscribe(res => {
  this.dataService.getData(res).subscribe(data=>{
    this.subdata=data;
    if (!this.subdata.find(x=>x.value==this.form.get("prop2").value))
      this.form.get("prop2").setValue(null);
  }).unsubscribe()
});

必须足够了,请参见

在尝试仅使用
SelectComponent
解决此问题时,尤其是
writeValue
,以下代码完成了此任务:

我将
select.component.ts
更改如下:

export class SomeObject {
  value: string;
  parameters: {[parameterName: string]: string} = {};
}

@Component({
  selector: "app-select",
  templateUrl: "./select.component.html",
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: SelectComponent,
    multi: true
  }]
})
export class SelectComponent implements ControlValueAccessor, OnChanges {
  @ViewChild("select", {static: true}) select: ElementRef;
  @Input() tableId: string;
  @Input() filter: { [parameterName: string]: string};

  returnedTable: SomeObject[];

  onChange: (_: any) => void;
  onTouched: () => void;

  selected: string;

  constructor(private tableService: TableService) { }

  loadTable(): void {
    this.tableService.getTable(this.tableId, this.filter)
      .subscribe(table => {
        this.returnedTable = table;
        if (!!this.select && !!this.select.nativeElement.value) {
          this.writeValue(this.select.nativeElement.value);
          this.onChange(this.selected);
        }
      });
  }

  ngOnChanges(): void {
    this.loadTable();
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  writeValue(value: string): void {
    if (!!this.returnedTable && !this.returnedTable.some(item => item.value === value)) {
      this.selected = null;
    } else {
      this.selected = value;
    }
  }
}
select.component.html
如下所示:

<select class="form-control" #select (change)="onChange($event.target.value)">
  <option hidden *ngIf="!selected" value=""></option>
  <option *ngFor="let item of returnedTable" [value]="item.value" [selected]="selected === item.value">{{item.value}}</option>
</select>


{{item.value}}

尝试仅使用
SelectComponent
尤其是
writeValue
解决此问题一段时间后,以下代码完成了工作:

我将
select.component.ts
更改如下:

export class SomeObject {
  value: string;
  parameters: {[parameterName: string]: string} = {};
}

@Component({
  selector: "app-select",
  templateUrl: "./select.component.html",
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: SelectComponent,
    multi: true
  }]
})
export class SelectComponent implements ControlValueAccessor, OnChanges {
  @ViewChild("select", {static: true}) select: ElementRef;
  @Input() tableId: string;
  @Input() filter: { [parameterName: string]: string};

  returnedTable: SomeObject[];

  onChange: (_: any) => void;
  onTouched: () => void;

  selected: string;

  constructor(private tableService: TableService) { }

  loadTable(): void {
    this.tableService.getTable(this.tableId, this.filter)
      .subscribe(table => {
        this.returnedTable = table;
        if (!!this.select && !!this.select.nativeElement.value) {
          this.writeValue(this.select.nativeElement.value);
          this.onChange(this.selected);
        }
      });
  }

  ngOnChanges(): void {
    this.loadTable();
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  writeValue(value: string): void {
    if (!!this.returnedTable && !this.returnedTable.some(item => item.value === value)) {
      this.selected = null;
    } else {
      this.selected = value;
    }
  }
}
select.component.html
如下所示:

<select class="form-control" #select (change)="onChange($event.target.value)">
  <option hidden *ngIf="!selected" value=""></option>
  <option *ngFor="let item of returnedTable" [value]="item.value" [selected]="selected === item.value">{{item.value}}</option>
</select>


{{item.value}}

取消选择选项:-
option.selected=false


Angular库的核心是函数反编译,用于
$scope
和嵌套表单,这是一个Angular特性,表明Angular团队不知道如何有效地使用HTML。HTML不允许嵌套表单,那你为什么要强行使用这种语言呢?麻烦太多了。当然,像布拉德利·格林(Bradley Green)这样的前Angular JS经理,你不可能期望有更好的表现。

要取消选择选项:-
option.selected=false


Angular库的核心是函数反编译,用于
$scope
和嵌套表单,这是一个Angular特性,表明Angular团队不知道如何有效地使用HTML。HTML不允许嵌套表单,那你为什么要强行使用这种语言呢?麻烦太多了。当然,像布拉德利·格林(Bradley Green)这样的前Angular JS经理,你不能期望有更好的表现。

只要在主选择值更改时将subselect设置为空白值,你就可以做到这一点,simpleThanks指出了这一点。这是我遗漏的另一个要求。如果
mainSelect
的上一个和新值包括
subSelect
的实际值,则
subSelect
的值需要保持有效。(我希望我试图归档的内容有一半清楚)。我将编辑我的问题以将此要求添加到其中。再次简单,只需浏览子列表并检查所选值是否存在于子列表中。如果是,则不要再次设置该值以保持该值,如果否,则将其设置为“”如果您可以发布解决方案的代码,那就太好了。只要在主选择值更改时将subselect设置为空值,SimpleThat就可以指出这一点。这是我遗漏的另一个要求。如果
mainSelect
的上一个和新值包括
subSelect
的实际值,则
subSelect
的值需要保持有效。(我希望我试图归档的内容有一半清楚)。我将编辑我的问题以将此要求添加到其中。再次简单,只需浏览子列表并检查所选值是否存在于子列表中。如果是,则不要再次设置该值以保持该值,如果否,则将其设置为“”如果您可以发布解决方案的代码,那就太好了。有没有办法不用订阅数据服务,也不用使用
select.component.ts
?在我面临这个问题的项目中,
select.component.ts
位于另一个模块中,需要进行验证