如何解决为什么我的输入组件在悬停而不是单击选项时会自动完成,但随后使输入字段无法使用?使用 stencilJS + React
我当前的 StencilJS 组件在下面的视频中给了我这个问题,该字段将在我不点击填充选项的情况下自动完成,然后该字段将无法使用。
在转换为 StencilJS 组件之前,它运行良好。现在神奇的是,我似乎在网上找不到任何问题。
相同的输入,但是当我单击一个选项时(忽略 404 屏幕,这是预期的)
有没有人在 Web 组件上遇到过这种情况?代码在这里:
import { Component,h,Prop } from '@stencil/core';
@Component({
tag: 'nwh-input',styleUrl: 'nwh-input.scss',shadow: true,})
export class NwhInput {
@Prop() customId?: string;
@Prop() customAriaLabel: string;
@Prop() required?: boolean;
@Prop() changeFunction?: (event: any) => void;
@Prop() type?: string;
@Prop() value?: string;
@Prop() label: string;
@Prop() disabled?: boolean;
@Prop() min?: number;
@Prop() max?: number;
@Prop() minLength?: number;
@Prop() maxLength?: number;
@Prop() name?: string;
@Prop() error?: string | boolean;
@Prop() success?: string | boolean;
@Prop() info?: string | boolean;
@Prop() inputRef?: any;
@Prop() size?: any;
@Prop() icon?: string;
@Prop() baseClassName: string;
@Prop() focusFunction: (event: any) => void;
@Prop() blurFunction: (event: any) => void;
@Prop() baseDefaultValue: string;
@Prop() labelClass: string;
render() {
return (
<div class="wrapper">
{this.icon && <i class={`input__icon fal ${this.icon}`} />}
{!this.disabled && (
<label class={this.labelClass}>
{this.label}
{this.required && <span class="required">*</span>}
</label>
)}
<input
id={this.customId}
class={this.baseClassName}
onInput={this.changeFunction}
onFocus={this.focusFunction}
onBlur={this.blurFunction}
type={this.type}
defaultValue={this.baseDefaultValue}
disabled={this.disabled}
aria-label={this.customAriaLabel}
min={this.min}
max={this.max}
minLength={this.minLength}
maxLength={this.maxLength}
name={this.name}
ref={this.inputRef}
/>
<nwh-helper-text error={this.error} info={this.info} success={this.success} />
</div>
);
}
}
对我来说没有什么是突出的问题。显然,如果我将 autoComplete="off"
添加到 input 标签,那么问题就解决了,但我认为完全删除此功能并不是要走的路。
请给我你的想法!
编辑:我已经把它弄糊涂了,但同样的问题仍然存在,只是在一个无样式的输入中
@Component({
tag: 'nwh-input',})
export class NwhInput {
@Prop() changeFunction?: (event: any) => void;
@Prop() name?: string;
@Prop() value?: string;
@Event() changed: EventEmitter<string>;
handleChange = e => {
this.value = e.target?.value || null;
this.changed.emit(this.value);
this.changeFunction(e);
};
render() {
return (
<div class="wrapper">
<input name={this.name} value={this.value} onInput={e => this.handleChange(e)} />
</div>
);
}
}
为托马斯编辑:
要使用组件,我有上面的 nwh-input.tsx,然后我有这个 components.ts 文件来创建 react 组件 components.ts
/* eslint-disable */
/* tslint:disable */
/* auto-generated react proxies */
import { createReactComponent } from './react-component-lib';
import type { JSX } from 'nwh-components';
export const NwhButton = /*@__PURE__*/createReactComponent<JSX.NwhButton,HTMLNwhButtonElement>('nwh-button');
export const NwhCheckbox = /*@__PURE__*/createReactComponent<JSX.NwhCheckbox,HTMLNwhCheckboxElement>('nwh-checkbox');
export const NwhDropdown = /*@__PURE__*/createReactComponent<JSX.NwhDropdown,HTMLNwhDropdownElement>('nwh-dropdown');
export const NwhHelperText = /*@__PURE__*/createReactComponent<JSX.NwhHelperText,HTMLNwhHelperTextElement>('nwh-helper-text');
export const NwhInput = /*@__PURE__*/createReactComponent<JSX.NwhInput,HTMLNwhInputElement>('nwh-input');
然后我在这里有我的 Input.tsx 反应组件:
import {
NwhDropdown,NwhInput,} from '../../../nwh-components-react/src/components';
import { InputSizes } from '../../constants';
import { IconType,OptionsType } from '../../types';
interface InputProps {
id?: string;
ariaLabel: string;
showRequiredAsterisk?: boolean;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
onChangeDropdown?: (event: React.ChangeEvent<HTMLSelectElement>) => void;
type?: string;
value?: string;
label: string;
disabled?: boolean;
isDropdown?: boolean;
defaultValue?: string;
optionsType?: OptionsType;
min?: number;
max?: number;
minLength?: number;
maxLength?: number;
className?: string;
// Unique input attribute referenced by react-hook-form to run validation.
name?: string;
// The error message that shows if there is a validation error on the input.
error?: string | boolean;
// True by default. Displays the error triangle on invalid fields.
showErrorTriangle?: boolean;
showErrorIcon?: boolean;
success?: string | boolean;
info?: string | boolean;
// The ref to the registered component that is being used for validation.
// TODO: Update to use non-legacy type.
inputRef?: LegacyRef<HTMLInputElement> & LegacyRef<HTMLSelectElement>;
// Sets the width of the input without using a wrapping div. Default is 100%.
size?: InputSizes;
iconType?: IconType;
iconColor?: string;
iconClassName?: string;
}
const Input: React.FC<InputProps> = ({
id,label,ariaLabel,onChange,onChangeDropdown,showRequiredAsterisk,type = 'text',value,disabled = false,isDropdown,optionsType,defaultValue,min,max,minLength,maxLength,className = '',error = '',success = '',info = '',name,inputRef,size = InputSizes.DEFAULT,iconType,}): JSX.Element => {
const [inputFocused,setInputFocused] = useState(false);
const inputErrorClass = error && 'input__error';
const inputSuccessClass = success && 'input__success';
const baseClassName = `input ${className} input--${size} ${inputErrorClass} ${inputSuccessClass}`;
const baseDefaultValue = defaultValue || value;
// Apply active class for animated input labels if your input is focused or already has a value
const focusClass =
(inputFocused && 'label--active') || (baseDefaultValue && 'label--active');
return (
<div className="input__wrapper">
{isDropdown ? (
<NwhDropdown
name={name}
customId={id}
customAriaLabel={ariaLabel}
baseClassName={baseClassName}
changeFunction={onChangeDropdown}
focusFunction={() => setInputFocused(true)}
blurFunction={() => !baseDefaultValue && setInputFocused(false)}
type={type}
disabled={disabled}
inputRef={inputRef}
error={error}
info={info}
success={success}
labelClass={`label ${focusClass}`}
label={label}
required={showRequiredAsterisk}
optionsType={optionsType}
baseDefaultValue={baseDefaultValue}
/>
) : (
<NwhInput
name={name}
customId={id}
customAriaLabel={ariaLabel}
baseClassName={baseClassName}
changeFunction={onChange}
focusFunction={() => setInputFocused(true)}
blurFunction={() => !baseDefaultValue && setInputFocused(false)}
type={type}
baseDefaultValue={baseDefaultValue}
disabled={disabled}
min={min}
max={max}
minLength={minLength}
maxLength={maxLength}
inputRef={inputRef}
error={error}
info={info}
success={success}
icon={iconType}
labelClass={`label ${focusClass}`}
label={label}
required={showRequiredAsterisk}
/>
)}
</div>
);
};
export default Input;
然后最终在页面中使用它,如下所示: create-account-email.tsx
import React,{ useState,useEffect } from 'react';
import { useDispatch,useSelector } from 'react-redux';
import { useForm } from 'react-hook-form';
import { useHistory } from 'react-router-dom';
import '../../assets/styles/styles.scss';
import * as createAccountActions from './actions/index';
import { hasValidEmail } from '../../util/formValidation';
import { AppRoutes,FormFieldErrorMessages,InputSizes } from '../../constants';
import { AnalyticsData } from '../../types';
import PageHeader from '../../components/page-header/page-header';
import Button from '../../components/button/Button';
import Input from '../../components/inputV2/Input';
import RequiredBadge from '../../components/requiredBadge/RequiredBadge';
import Envelope from '../../assets/images/envelope.svg';
const CreateAccountEmail: React.FC = (): JSX.Element => {
// Redux hooks
const initiator = useSelector(
(state: InitialState) => state.account?.accountInfo?.initiator,);
// Redux hooks
const dispatch = useDispatch();
const history = useHistory();
// State hooks
const [email,setEmail] = useState('');
const [processingRequest,setProcessingRequest] = useState(false);
// React-hook-form hooks.
const { register,handleSubmit,errors } = useForm({
reValidateMode: null,});
const determineNavigation = () => {
history.push(AppRoutes.CREATE_ACCOUNT_ENTER_CODE);
};
// Run form submission validations and route accordingly.
const handleFormSubmission = e => {
e.preventDefault();
// Do not submit the form again if request is already processing.
if (processingRequest) {
return;
}
// Disables the submit button and subsequent button clicks from triggering
// another request to the server.
setProcessingRequest(true);
dispatch(createAccountActions.setEzEmail(email));
// Run handleSubmit hook to validate form fields using react-hook-form.
// If there are no form errors,proceed with next action.
handleSubmit(determineNavigation)();
};
// Reset processing state if form errors exist.
useEffect(() => {
const hasFormErrors = !!Object.keys(errors).length;
if (hasFormErrors && processingRequest) {
setProcessingRequest(false);
}
});
// Analytics
const createAccountEmailButton: AnalyticsData = {
testId: 'CreateAccountEmail-Button-1',initiator,};
return (
<>
<PageHeader headerText="Create an account" />
<div className="create-account-email container">
<img
src={Envelope}
alt="Envelope"
className="create-account-email__icon"
/>
<RequiredBadge />
<h2 className="header-2 create-account-email__header">
What's your email?
</h2>
<form onSubmit={handleFormSubmission}>
<div className="create-account-email__input">
<Input
label="Email address"
ariaLabel={email || 'Email address'}
value={email}
name="email"
onChange={e => {
setEmail(e.target.value);
}}
inputRef={register({ validate: () => hasValidEmail(email) })}
error={errors?.email && FormFieldErrorMessages.REQUIRED}
size={InputSizes.LARGE}
showRequiredAsterisk
info={`We’ll send a confirmation code to this email`}
/>
</div>
<Button
onClick={handleFormSubmission}
analyticsData={createAccountEmailButton}
text="Continue"
disabled={processingRequest}
/>
</form>
</div>
</>
);
};
export default CreateAccountEmail;
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。