javascript - 无法将值绑定(bind)到 setter 中 p-autocomplete 中的 ngModel

标签 javascript angular typescript primeng

我有组件,我在其中使用 primeNG p-autocomplete

这是该组件的 html

 <form #addressForm="ngForm" novalidate name="AddressForm">
<div class="form-group">
    <label for="Line1">{{ 'AddressLine1' | localize }} *</label>
    <p-autoComplete
        #addressLine1="ngModel"
        [(ngModel)]="selectedAddresses"
        [suggestions]="addresses"
        field="line1"
        [inputStyle]="{ width: '100%' }"
        name="line1"
        (completeMethod)="searchAddress($event)"
        [size]="10"
        placeholder="{{ 'Line1Placeholder' | localize }}"
        (onSelect)="onSelectAddress($event)"
        [minLength]="3"
        required
        (change)="checkValidity()"
    ></p-autoComplete>
    <validation-messages [formCtrl]="addressLine1"></validation-messages>
  {{address.line1}}
</div>

<div class="form-group">
    <label for="Line2">{{ 'AddressLine2' | localize }}</label>
    <input
        id="Line2"
        class="form-control"
        #line2Input="ngModel"
        type="text"
        name="Line2"
        placeholder="{{ 'Line2Placeholder' | localize }}"
        [(ngModel)]="address.line2"
        maxlength="128"
        (change)="checkValidity()"
    />
</div>
<div class="form-group">
    <label for="Line3">{{ 'AddressLine3' | localize }} </label>
    <input
        id="Line3"
        class="form-control"
        #line3Input="ngModel"
        type="text"
        name="Line3"
        [(ngModel)]="address.line3"
        maxlength="128"
        (change)="checkValidity()"
    />
    <validation-messages [formCtrl]="line3Input"></validation-messages>
</div>

这是组件的 typescript 部分

  import { Component, Injector, forwardRef, ViewChild, AfterContentChecked, ElementRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR, NG_VALIDATORS, ValidationErrors } from '@angular/forms';
import { AddressType } from '@shared/AppEnums';
import { AppComponentBase } from '@shared/common/app-component-base';
import { AddressDto } from '@shared/service-proxies/service-proxies';
import { SelectItem } from 'primeng/primeng';
import PlaceResult = google.maps.places.PlaceResult;
import { Feature } from '../../dto/mapboxOutput';
import { MapboxServiceService } from '../mapbox-service';

@Component({
    selector: 'edit-main-address',
    templateUrl: './edit-main-address.component.html',
    providers: [
        { provide: NG_VALUE_ACCESSOR, useExisting: EditMainAddressComponent, multi: true },
        {
            provide: NG_VALIDATORS,
            useExisting: forwardRef(() => EditMainAddressComponent),
            multi: true,
        },
    ],
})
export class EditMainAddressComponent extends AppComponentBase implements ControlValueAccessor, AfterContentChecked {
    @ViewChild('addressForm') addressForm;
    @ViewChild('search') public searchElement: ElementRef;
    @ViewChild('postCode') public postCodeElement: ElementRef;
    @ViewChild('town') public townElement: ElementRef;
    @ViewChild('country') public countryElement: ElementRef;
    required: string | boolean;

    private changed = [];
    private touched = [];


    disabled: boolean;
    address: AddressDto = new AddressDto();
    addressTypes: SelectItem[] = [];
    addresses: any[] = [];
    selectedAddresses: string;
    public lat: any;
    public lng: any;
    public postCode: string;
    public country: string;
    public city: string;
    public line1: any;

    constructor(injector: Injector, private mapboxService: MapboxServiceService) {
        super(injector);
        this.addressTypes.push({ label: this.l('Address.Main'), value: AddressType.Main });
        this.addressTypes.push({ label: this.l('Address.Billing'), value: AddressType.Billing });
        this.addressTypes.push({ label: this.l('Address.Delivery'), value: AddressType.Delivery });
        this.addressTypes.push({ label: this.l('Address.Correspondence'), value: AddressType.Correspondence });
    }

    ngAfterContentChecked(): void {
        this.checkValidity();
    }

    checkValidity(): void {}

    get adressResult(): AddressDto {
        return this.address;
    }

    set addressResult(value: AddressDto) {
        if (this.address !== value) {
            this.address = value;
            this.selectedAddresses = value.line1;
            this.changed.forEach(f => f(value));
        }
    }

    registerOnChange(fn: any): void {
        this.changed.push(fn);
    }

    registerOnTouched(fn: any): void {
        this.touched.push(fn);
    }

    setDisabledState(isDisabled: boolean): void {
        this.disabled = isDisabled;
    }

    writeValue(obj: AddressDto): void {
        if (obj) {
            this.addressResult = obj;
            this.selectedAddresses = this.address.line1;
            this.checkValidity();
        }
    }

    validate(): ValidationErrors {
        if (!this.addressForm.valid) {
            return { message: 'custom error' };
        }
        return null;
    }

    registerOnValidatorChange(fn: () => void): void {
        this.checkValidity = fn;
    }

    searchAddress(event: any): any {
        const searchTerm = event.query.toLowerCase();
        if (searchTerm && searchTerm.length > 0) {
            this.mapboxService.addressSearch(searchTerm).subscribe((features: Feature[]) => {
                this.addresses = [...features.map(e => ({ name: e.place_name, id: e.place_name, feature: e }))];
            });
        } else {
            this.addresses = [];
        }
    }

    onSelectAddress(event: any): any {
        if (event.feature.id.startsWith('address')) {
            this.address.line1 = event.name;
            this.address.longitude = event.feature.center[0];
            this.address.latitude = event.feature.center[1];
            this.address.postTown = event.feature.context.filter(element => element.id.startsWith('place'))[0].text;
            this.address.county = event.feature.context.filter(element => element.id.startsWith('district'))[0].text;
            this.address.country = event.feature.context.filter(element => element.id.startsWith('country'))[0].text;
            this.address.postCode = event.feature.context.filter(element => element.id.startsWith('postcode'))[0].text;
        }
        if (event.feature.id.startsWith('postcode')) {
            this.address.line1 = event.name;
            this.address.longitude = event.feature.center[0];
            this.address.latitude = event.feature.center[1];
            this.address.postTown = event.feature.context.filter(element => element.id.startsWith('place'))[0].text;
            this.address.county = event.feature.context.filter(element => element.id.startsWith('district'))[0].text;
            this.address.country = event.feature.context.filter(element => element.id.startsWith('country'))[0].text;
            this.address.postCode = event.feature.text;
        }
    }
    ngOnInit(): void {}
}

我的问题是 ngModel 的所有字段都设置得很好,但 p-autocomplete 未设置

我尝试将值设置为 selectedAddresses,如下所示 this.selectedAddresses = value.line1; 这是字符串,如果我制作 console.log(this.selectedAddresses)我在控制台中看到它。但它没有设置为 p-autocomplete 字段,我在输入中没有看到值

最佳答案

selectedAddresses 的类型从 string 更改为 any,然后将 p- 的 field 指令更改为 any自动完成将完​​成剩下的工作:

selectedAddresses: any;

现在 field="line1" 将在您的输入字段中显示 selectedAddresses.line1

<p-autoComplete
        #addressLine1="ngModel"
        [(ngModel)]="selectedAddresses"
        [suggestions]="addresses"
        field="line1"
        [inputStyle]="{ width: '100%' }"
        name="line1"
        (completeMethod)="searchAddress($event)"
        [size]="10"
        placeholder="{{ 'Line1Placeholder' | localize }}"
        (onSelect)="onSelectAddress($event)"
        [minLength]="3"
        required
        (change)="checkValidity()"
    ></p-autoComplete>

关于javascript - 无法将值绑定(bind)到 setter 中 p-autocomplete 中的 ngModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60373095/

相关文章:

angular - 为什么拦截器不返回数据给订阅者?

angular - Angular 6 中如何仅将一个值从一个组件传递到另一组件?

angular - 在 Ionic + Angular 中构建身份验证拦截器时出错

javascript - 如何从一个类中获取按钮内使用的所有类名?

javascript - 是否可以从另一个按钮的单击事件触发按钮客户端单击事件?

javascript - 使用对话框中的输入订阅可观察的异步 map 结果,使用 map 结果来路由

typescript - 使用 Angular2 处理 404

angular - MemoizedSelector 不可分配给类型为 'string' 的参数

javascript - 将菜单树代码从 jquery 1.7.1 迁移到 1.9.1

javascript - 在 Safari/Opera 上启用数据列表的脚本