自定义HTML元素不会对属性更改做出反应

时间:2020-07-28 08:02:45

标签: javascript forms

抱歉,我的英语不是我的母语。) 我有两个自定义HTML元素:SignUpForm(父级)和CustomInput(子级)。在SingUpForm中,我验证输入-检查是否为空。如果是,则通过element.setAttribute(name,val)设置属性error-text,然后在CustomInput中“捕获”此更改,并在span中设置验证文本。 但是在验证并调用elem.setAttribute(name,val)之后,我的CustomInput对此更改没有反应。我不明白为什么。我做错了什么? 在下面,您可以看到我的自定义元素和BaseComponent-它们都是它们的父类。

//////////////////
export default class BaseComponents extends HTMLElement {
    constructor() {
        super();
        this.rendered = false;
    }

    static get is() {
        return this.nodeName;
    }

    $(selector) {
        return this.querySelector(selector);
    }

    $$(selector) {
        return this.querySelectorAll(selector);
    }

    connectedCallback() {
        if (!this.rendered) {
            this.innerHTML = this.render();
            this.rendered = true;
        }
    }
    
    render() {
        return ``;
    }
}

///////////////////

export default class SignUpForm extends BaseComponent {
    static nodeName = 'sign-up-form'

    constructor() {
        super();
        this.name = 'sigUpForm';
        this.emptyFieldErrorText = 'This field is required';
    }

    connectedCallback() {
        super.connectedCallback();

        this.$(`#${this.name}`).addEventListener('submit', (e) => {
            this.collectAndSendData(e);
        });
    }

    collectAndSendData(event) {
        event.preventDefault();
        
        const form = event.target;
        const usernameInput = form.elements.username;
        const emailInput = form.elements.email;
        const passwordInput = form.elements.password;
        const passwordInput2 = form.elements.repeat_password;

        if (isEmpty(usernameInput.value)) {
            usernameInput.setAttribute('error-text', this.emptyFieldErrorText);
            console.log("collectAndSendData -> usernameInput", usernameInput.getAttribute('error-text'))
        }
    }

    render() {
        return `
            <form id="${this.name}" autocomplete="off" novalidate>
                <fieldset>
                    <legend> Sign up </legend>

                    <custom-input name="username" 
                            type="text"
                            placeholder="Username"
                            form="${this.name}"
                            required>
                    </custom-input>

                    <custom-input name="email" 
                            type="text"
                            placeholder="Email"
                            form="${this.name}"
                            required>
                    </custom-input>

                    <custom-input name="password" 
                            type="password"
                            placeholder="Password"
                            form="${this.name}"
                            required>
                    </custom-input>

                    <custom-input name="repeat_password" 
                            type="password"
                            placeholder="Repeat password"
                            form="${this.name}"
                            required>
                    </custom-input>
                    
                    <custom-button tag="button" 
                            form="${this.name}"
                            value="SignUp" 
                            color-class="second">
                            type="submit"
                    </custom-button>
                </fieldset>
            </form>
        `
    }
}
////////////////

export default class CustomInput extends BaseComponent {
    static nodeName = 'custom-input';

    constructor() {
        super();
        this.name = null;
        this.type = null;
        this.placeholder = null;
        this.disabled = false;
        this.pattern = new RegExp(/^.$/);
        this.required = false;
        this.value = '';
        this.form = null;
    }

    static get observedAttributes() {
        return ['name', 'type', 'placeholder', 'form', 'disabled', 'pattern', 'required', 'value', 'error-text']
    }

    connectedCallback() {
        super.connectedCallback();
        this.setBooleanAttributes();
    }

    attributeChangedCallback(attrName, oldVal, newVal) {
        console.log("CustomInput -> attributeChangedCallback -> attrName", attrName)
        switch(attrName) {
            case 'name':
                this.name = newVal;
                break;
            case 'type':
                this.type = newVal;
                break;
            case 'placeholder':
                this.placeholder = newVal;
                break;
            case 'required':
                this.required = true;
                break;
            case 'value':
                this.value = newVal;
                break;
            case 'form':
                this.form = newVal;
                break;
            case 'error-text':
                console.log('11111111111111')
                this.errorText = newVal;
                break;
        }
    }

    set errorText(newVal) {
        const errorContainer = this.$('js-error-text');
        errorContainer.innerHTML = '';
        console.log("CustomInput -> setErrorText -> errorContainer", errorContainer)
        errorContainer.append(newVal);
    }

    get errorText() {
        const errorContainer = this.$('js-error-text');
        return errorContainer.innerHTML;
    }

    setBooleanAttributes() {
        const inputEl = this.$('input');

        if (this.disabled) {
            inputEl.disabled = true;
        }

        if (this.required) {
            inputEl.required = true;
        }

    }

    render() {
        return `
            <input id="${this.name}" 
                   name="${this.name}"
                   type="${this.type}" 
                   placeholder="${this.placeholder}"
                   pattern="${this.pattern}"
                   value="${this.value}"
                   form="${this.form}"
                   class="custom-input__input" />
            
            <span class="custom-input__error-text js-error-text"></span>

            <label for="${this.name}">
                ${this.name}
            </label>
        `
    }
}

1 个答案:

答案 0 :(得分:0)

form.elements.username返回您的自定义输入嵌套(本机)输入,该输入与自定义输入具有相同的name

您只是将属性设置在错误的元素(本机输入)上,从而永远不会调用attributeChangedCallback