Валидиране на Aurelia - Формулярът се зарежда с данни от извличане - валидирането оценява пълните полета като празни

Имам формуляр, който успешно зареждам с данни от извличане. Ако след това щракна върху запазване на този формуляр, Aurelia Validation оценява тези текстови полета на формуляра, които имат данни, като празни и показва това като грешка под бутона за запазване - снимката по-долу.

Валидирането работи перфектно на празен формуляр, но за формуляр със заредени стойности, сякаш формулярът се държи като празен.

Със сигурност, ако има знаци в текстовото поле или чрез въвеждане, или чрез зареждане от извличане, трябва да оцени това в контекста на „задължително“ и да премине?

В момента не е, когато се зарежда от извличане.

Код

Ето модела за изглед на машинопис:

    import { HttpClient } from "aurelia-fetch-client";
    import { autoinject, inject, NewInstance, PLATFORM } from "aurelia-framework";
    import { Router, activationStrategy } from "aurelia-router";
    import {
        ValidationControllerFactory,
        ValidationController,
        ValidationRules,
        validateTrigger
    } from "aurelia-validation";
    import { BootstrapFormRenderer } from "../../../../services/bootstrapFormRenderer/bootstrapFormRenderer";
    //import  from '../../../../services/customValidationRules/customValidationRules'

    import { AuthService } from "../../../../services/auth/auth-service"

    @autoinject
    export class Client {
        controller: ValidationController;
        client = new ClientDetails;
        job: Job;
        visits = Array();
        hasClientId: boolean;
        heading: string = "New Client";
        headingIcon: string = "fa-user-plus";

        username: string;


        constructor(
            private authService: AuthService,
            private router: Router,
            private controllerFactory: ValidationControllerFactory
        ) {
            this.router = router;
            this.controller = controllerFactory.createForCurrentScope();
            this.controller.addRenderer(new BootstrapFormRenderer());
            this.controller.addObject(this)
            this.controller.addObject(this.client);

        }

        // Required to reload new instance.
        determineActivationStrategy() {
            return activationStrategy.replace; //replace the viewmodel with a new instance
            // or activationStrategy.invokeLifecycle to invoke router lifecycle methods on the existing VM
            // or activationStrategy.noChange to explicitly use the default behavior
        }

        activate(parms, routeConfig) {
            this.hasClientId = parms.id;

            if (this.hasClientId) {
                const headers = this.authService.header();

                fetch("/api/Client/edit/" + parms.id, {
                    method: "GET",
                    headers
                })
                    .then(response => response.json())
                    .then(data => {
                        this.client = data
                    })
                this.heading = "Edit Client"; // An id was submitted in the route so we change the heading as well.
                this.headingIcon = "fa-pencil-square-o";
            }
            return null;
        }

        submitClient() {
            console.log("gets  Here");
            console.log("this.controller.validate(): ", this.controller.validate());
            //this.controller.validate();
            if (this.controller.validate()) {
                console.log("Hi!");
            }
        }

        rowSelected(jobId: number) {
            let job = this.client.jobs.filter(f => f.id === jobId);
            if (job && job.length > 0) {
                var jobVisits = job.map(j => { return j.jobVisits; })[0];
                this.visits = jobVisits;
            }
        }
    }


    export class ClientDetails {

        clientId: number;
        clientNo: number;
        company: boolean;
        companyName: string;
        abn: string;
        isWarrantyCompany: boolean;
        requiresPartsPayment: boolean;
        clientFirstName: string;
        clientLastName: string;
        email: string;
        mobilePhone: string;
        phone: string;
        notes: string;

        address: AddressDetails;

        jobs: Job[];

        bankName: string;
        bankBSB: string;
        bankAccount: string;
        active: boolean;
        deActivated: string;
        activity: boolean;
        dateCreated: string;
        dateUpdated: string;

        creatorId: number;
        creatorName: string;
    }

    class Job {
        id: number;
        agentJobNo: number;
        jobNo: number;
        jobType: string;
        jobVisits: Visit[]
        numberOfVisits: number;
        status: string;
    }

    class Visit {
        jobVisitId: number;
        dateCreated: string;
        visitDate: string;
        startTime: string;
        endTime: string;
    }

    class AddressDetails {
        address1: string;
        address2: string;
        suburb: string;
        postcode: string;
        stateShortName: string;
        addressLocationId: number;
    }

    // Validation Rules.
    ValidationRules
        .ensure((a: ClientDetails) => a.companyName).required()
            .when((a: ClientDetails) => a.company === true)
            .withMessage('Company name is required if client is a company.')
        .ensure((a: ClientDetails) => a.clientLastName).required()
        .ensure((a: ClientDetails) => a.mobilePhone).required()
        .on(ClientDetails)

Извличането е във функцията за активиране и се извлича само ако има предоставен идентификатор. Извличането зарежда "клиента" с данните, които се връщат. Това работи и имам формуляр с всички показани данни от извличането.

Ако обаче щракна върху бутона „Запазване“, дори ако двете полета „lastName“ и „mobilePhone“ имат стойности в тях, функцията „submitClient()“ се задейства и „this.controller.validate()“ оценява тези полета като празни .

Не трябва ли да вижда, че тези полета имат стойности в тях? Има ли нещо, което пропускам тук?

Ето как изгледът има "lastName" - имайте предвид, че присъства "& validate".

                <div class="col-md-6">
                    <div class="col-md-3">
                        <div class="form-group">
                            <label class="control-label pull-right" for="lastname">Last Name:&nbsp;</label>
                        </div>
                    </div>
                    <div class="col-md-9">
                        <div class="form-group">
                            <input type="text" value.bind="client.clientLastName & validate" class="form-control" id="lastname" placeholder="Last Name...">
                        </div>
                    </div>
                </div>

въведете описание на изображението тук


person si2030    schedule 20.01.2018    source източник


Отговори (1)


Когато зареждате съществуващ клиент от сървъра, вие настройвате свойството this.client да бъде прост JSON обект. Вече няма да бъде екземпляр на ClientDetails и следователно правилата за валидиране няма да работят, тъй като работят само на ClientDetails екземпляри.

Ще трябва да създадете нов екземпляр на ClientDetails и да го попълните от обекта data, върнат от fetch. Може да се направи ръчно чрез създаване на конструктор или метод за картографиране в ClientDetails, който приема обект с данни и картографира към всяко свойство ClientDetails (this.clientId = data.clientId и т.н.).

Като алтернатива можете да имате някаква обща функция за картографиране, която да прави картографирането по имена на свойства. Не съм много запознат с TypeScript, но този SO въпрос има много решения как да направите това.

person Miroslav Popovic    schedule 20.01.2018
comment
Внедрена е опция 4 от споменатия SO въпрос и тя проработи. - person si2030; 21.01.2018