angular - 如何让我的 ngModel 在我的 ng-template 中自动工作?
问题描述
我有很多带有标签和输入的表单组。我想制作可重用的 ng-template
所以我有
<div class="form-group">
<label class="form-control-label" for="address">Address</label>
<input [disabled]="isTheLoggedInUserAdmin" id="address" class="form-control form-
control-alternative"
[(ngModel)]="sharedService.tempUser.address" name="address" type="text">
</div>
并使用 ng-template 将其转换为
<ng-template [ngTemplateOutlet]="formGroup"
[ngTemplateOutletContext]="{data: {inputId:'address', label:'Address', ngModel:
sharedService.tempUser.address }}"
></ng-template>
<ng-template #formGroup let-data="data">
<div class="form-group">
<label class="form-control-label" [for]="data.inputId">{{data.label}}</label>
<input [disabled]="isTheLoggedInUserAdmin" [id]="data.inputId" class="form-control form-control-
alternative"
[(ngModel)]="sharedService.tempUser.address" [name]="data.inputId" type="text">
</div>
</ng-template>
所以我在这里自动传递 inputId,标签名称,现在 ngModel 是硬编码的,它指向sharedService.tempUser.address
但是我的 ng-template 需要是动态的,所以使用 ng-template 调用我应该传递参数like label for example
- 参数 shpuld 指向我的打字稿文件中的不同 ngModel 变量
但是当我这样做时
<div class="form-group">
<label class="form-control-label" [for]="data.inputId">{{data.label}}</label>
<input [disabled]="isTheLoggedInUserAdmin" [id]="data.inputId" class="form-control form-control-alternative"
[(ngModel)]="data.ngModel" [name]="data.inputId" type="text">
</div>
nowdata.ngModel
是从 ng-template 调用发送的——也就是说sharedService.tempUser.address
,我从中得到了实际值,sharedService.tempUser.address
但是 *问题是 ngModel 在这里不起作用`
当我输入内容时,它没有更新
我该如何解决这个问题?
解决方案
您可能想编写一个实现ControlValueAccessor
作为替代方案。这是创建与 Form API 兼容的可重用组件的 Angular 官方方法。一个最小的例子是这样的:
my-custom-control.component.html
<div class="form-group">
<label class="form-control-label" for="{{data.field}}">{{data.label}}</label>
<input [disabled]="disabled" id="{{data.field}}" class="form-control form-control-alternative"
[value]="value" name="{{data.field}}" type="text"
(change)="onChange($event)" (blur)="onBlur($event)">
</div>
my-custom-control.component.ts
/**
import things....
**/
@Component({
selector: 'MyControl',
templateUrl: './my-custom-control.component.html',
styleUrls: ['./my-custom-control.component.scss'],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => MyControlComponent),
multi: true
}]
})
export class MyControlComponent implements OnInit, ControlValueAccessor {
@Input() value: any;
@Input() data: { 'field': string, 'label': string } = { field: "default", label: "default" };
@Input() disabled: boolean = false;
setDisabledState(isDisabled: boolean) {
this.disabled = isDisabled;
}
propagateChange = (_: any) => { };
propagateTouch = () => { };
registerOnChange(fn) {
this.propagateChange = fn;
}
registerOnTouched(fn) {
this.propagateTouch = fn;
}
constructor() {
}
ngOnInit() {
}
// value changed from ui
onChange(event: any){
this.value = event.target.value;
// tell angular that the control value is changed
this.propagateChange(this.value);
}
// received value from form api
writeValue(newFormValue: any) {
this.value = newFormValue;
}
// tell angular that this form control is touched
onBlur(event: any) {
this.propagateTouch();
}
}
之后,您可以重用此组件,例如:
<!-- With FormGroup -->
<form [formGroup]="myForm">
<MyControl formControlName="address" [disabled]="isTheLoggedInUserAdmin" [data]="{ field: 'address', label: 'Address' }">
<MyControl formControlName="title" [disabled]="isTheLoggedInUserAdmin" [data]="{ field: 'title', label: 'Title' }">
<MyControl formControlName="surname" [disabled]="isTheLoggedInUserAdmin" [data]="{ field: 'surname', label: 'Surname' }">
<!-- other controls... -->
</form>
<!-- Without FormGroup -->
<div>
<MyControl [(ngModel)]="myModel.address" [ngModelOptions]="{standalone: true}" [disabled]="isTheLoggedInUserAdmin" [data]="{ field: 'address', label: 'Address' }">
<MyControl [(ngModel)]="myModel.title" [ngModelOptions]="{standalone: true}" [disabled]="isTheLoggedInUserAdmin" [data]="{ field: 'title', label: 'Title' }">
<MyControl [(ngModel)]="myModel.surname" [ngModelOptions]="{standalone: true}" [disabled]="isTheLoggedInUserAdmin" [data]="{ field: 'surname', label: 'Surname' }">
<!-- other controls... -->
</div>
ngFor
如果你有一个模型描述数组,它也可以很容易地写入一个。
编辑:添加示例 scss 样式。
my-custom-control.component.scss
@import "variable.scss";
:host(.ng-dirty.ng-invalid, .ng-touched.ng-invalid) input {
border-color: $c-alert !important;
border-width: 2px;
border-style: solid;
color: $c-alert;
}
推荐阅读
- apache-superset - 如何在 Apache Superset 的自定义可视化 D3 组件中实现弹出窗口
- javascript - 打字头如何只允许列出值,否则会发出警报?
- spring-boot - 我们可以从 manifist.yml 文件中的 application.property 文件中读取属性吗
- angular - Angular 测试,为不同的测试用例动态改变 ActivatedRoute 参数
- dart - Flutter 从应用程序中删除录制的视频文件
- python - 如何用漂亮的汤将更多值附加到一系列 xml 标签上?
- rust - 在 STDIN 之后编译然后在输入上进行数学运算时得到不匹配的类型
- nginx - 在 nginx 配置服务器名称中使用通配符
- android - 深度链接 - 如何?
- python - 在python中为每个子图添加一条对角线