【问题标题】:How can I automatically generate a new input area when user started to enter text?当用户开始输入文本时,如何自动生成新的输入区域?
【发布时间】:2020-09-16 08:54:24
【问题描述】:

我想动态生成输入。搜索了几乎所有样本,它们通过单击按钮生成输入。没关系,但我需要一些不同的东西。当用户开始输入输入时,我想创建第二个输入,当用户输入第二个时,然后像这样创建第三个输入..

我的问题是当用户输入输入时,它会创建许多输入(字母计数=输入)。我必须立即解决这个问题。我尝试了一些技巧,但他们无法工作。感谢您的帮助。你可以在 Codepen 中查看。

  <div class="container1">
      <button class="add_form_field">
        Add New Field &nbsp;
        <span style="font-size: 16px; font-weight: bold;">+ </span>
      </button>
      <div class="divInput firstChild">
        <input type="text" autocomplete="off" name="mytext[]" />
      </div>
    </div>
 $(document).ready(function () {
        var max_fields = 10;
        var wrapper = $(".container1");
        var add_button = $(".add_form_field");

        var inputs = document.querySelectorAll(".divInput");
        let xs = [];
        var x = 1;
        $(add_button).click(function (e) {
          e.preventDefault();
          if (x < max_fields) {
            x++;

            $(wrapper).append(
              '<div class="divInput"><input type="text" autocomplete="off" name="mytext[]"/><a href="#" class="delete"></a></div>'
            ); //add input box
          } else {
            alert("You Reached the limits");
          }
        });



        $(wrapper).on("keyup", "input", function (e) {
          e.preventDefault();

          if ($(this).val() == "") {
            //when user cleaned input then delete it
            $(this).parent("div").remove();
            x--;
            return;
          } else if ($(this).val() != "") {
            //dont use click check if length>0 then use this trick to add new input
            $(add_button).trigger("click");
            return;
          }


          if (x == 0) {
            //if user tries to delete last input then create a new one
            console.log("xx", x);
            $(wrapper).append(
              '<div class="divInput"><input type="text" autocomplete="off" name="mytext[]"/><a href="#" class="delete"></a></div>'
            ); //add input box
            x = 1;
            console.log("xx", x);
            return;
          }
        });
      });



https://codepen.io/otontas11/pen/BaogrZR

【问题讨论】:

    标签: javascript html jquery reactjs web


    【解决方案1】:

    首先,您需要将当前id存储在输入中,当用户输入时创建一个事件并检查输入id并检查是否已添加,如果没有则继续。

    您需要将事件附加到 body,因为您正在动态创建元素。

    这是你要找的吗?

    <div id="container">
        <div class="generatedChild">
            <input type="text" childId="1" autocomplete="off" name="mytext[]"/>
        </div>
    </div>
    <script>
    $(function(){
        var max_fields = 10;
        var wrapper = $('#container');
        // attach the event to the Body, so all generated inputs will be listened by our event
        $('body').on('input','.generatedChild input' ,function(e){
            currentId = $(this).attr("childid");
            childId = parseInt(currentId) + 1;
            childOfThisInput = $(`input[childid=${childId}]`);
    
            // check if is already added or if exceeds the maximum fields number
            if(currentId > max_fields || childOfThisInput.length === 1) return;
    
            $div = $("<div>", {class: "generatedChild"});
            $input = $('<input>', {childid: childId, autocomplete:"off", name:"mytext[]", type: "text"});
            $div.append($input);
            wrapper.append($div);
    
        });
    });
    </script>
    

    更新: 如果您需要让用户删除一些生成的输入,您可以尝试以下操作:

    $(function(){
        var max_fields = 10;
        var wrapper = $('#container');
        var inputsLength = 1;
        // attach the event to the Body, so all generated inputs will be listened by our event
        $('body').on('keydown','.generatedChild input' ,function(e){
            currentId = $(this).attr("childid");
            childId = parseInt(currentId) + 1;
            childOfThisInput = $(`input[childid=${childId}]`);
            if($(this).val() === "" && e.key === 8 && inputsLength > 1 )
                return remove_input($(this));
            // check if is already added or if exceeds the maximum fields number
            if(inputsLength > max_fields || childOfThisInput.length === 1 || e.key === 8) return;
                add_input(childId);
        });
        function add_input(childId){
            $div = $("<div>", {class: "generatedChild"});
            $input = $('<input>', {childid: childId, autocomplete:"off", name:"mytext[]", type: "text"});
            $div.append($input);
            wrapper.append($div);
            ++inputsLength;
        }
        function remove_input(element){
            element.parent('.generatedChild').remove();
            // let's focus the last generated input, so user won't need focus the input again
            $('.generatedChild input:last').focus();
            --inputsLength;
        }
    });
    

    【讨论】:

    • 是的,它有效。只是一个小错误,当我试图删除输入值时,我遇到了一个问题if ($(this).val() == "") { $(this).parent(".generatedChild").remove(); },即使用户想要逐个删除所有输入,也应该只保留一个输入
    • 我明白了。我编辑了我的答案并添加了一些代码,让您以正确的方式删除生成的输入
    • 是的,它可以工作,我只是更改了keydown to keyup nnd 后来它工作正常。在做了一些安排后,我开始使用它。你拯救了我的一天,也许是一周:)
    【解决方案2】:

    我知道这主要是一个的观点,但 IMO 你不应该将 jQuery 与 react 混合使用,它们使用相当正交的方式来完成 UI 操作。

    这是我完成这个设计的一种方式

    const createInitialState = initialValues =>
      initialValues.map(value => ({ id: uuidv4(), value })); // id used internally
    
    const createOnChangeValues = values => values.map(({ value }) => value);
    
    const InputList = ({ defaultValues = [], onChange }) => {
      const renderRef = useRef(null);
      const inputRef = useRef(null);
      const [values, setValues] = useState(createInitialState(defaultValues));
      const [inputFocused, setInputFocused] = useState(false);
      const [inputValue, setInputValue] = useState("");
    
      useEffect(() => {
        if (renderRef.current) {
          onChange && onChange(createOnChangeValues(values));
        }
        renderRef.current = true;
      }, [onChange, values]);
    
      const addValue = value => {
        if (value) {
          setValues(values => [...values, { id: uuidv4(), value }]);
          setInputValue("");
        }
      };
    
      const updateValue = index => e => {
        const updateValue = e.target.value;
        if (updateValue) {
          setValues(values =>
            values.map(({ id, value }, i) => ({
              id,
              value: index === i ? updateValue : value
            }))
          );
        } else {
          setValues(values => values.filter((_, i) => i !== index));
        }
      };
    
      useEffect(() => {
        if (!inputFocused && inputValue) {
          addValue(inputValue);
          inputRef.current.focus();
        }
      }, [inputFocused, inputValue]);
    
      const submitHandler = e => {
        e.preventDefault();
        addValue(inputValue);
      };
    
      const resetHandler = e => {
        e.preventDefault();
        setInputValue("");
      };
    
      return (
        <Fragment>
          <form id="inputForm" onReset={resetHandler} onSubmit={submitHandler} />
    
          {values.map(({ id, value }, i) => (
            <div key={id}>
              <input value={value} onChange={updateValue(i)} />
            </div>
          ))}
    
          <div>
            <input
              form="inputForm"
              ref={inputRef}
              type="text"
              value={inputValue}
              onFocus={() => setInputFocused(true)}
              onBlur={() => setInputFocused(false)}
              onChange={e => setInputValue(e.target.value)}
            />
          </div>
    
          {inputValue && (
            <div>
              <input />
            </div>
          )}
        </Fragment>
      );
    };
    

    要点是你有 一些 当前正在使用的输入数组,并且你总是渲染一个额外的空白输入。一旦用户开始填充新的空白输入,它就会在失去焦点时成为输入数组的一部分。如果任何输入变为空白,则将其从数组中删除。大部分逻辑是管理从新输入/空输入到数组中一个的交换并保持焦点。

    用法

    <InputList defaultValues={[... input values from state]} onChange={... values from inputs in array} />
    

    【讨论】:

    • 这正是我需要的,但问题是它是用 react js 编写的:) 非常感谢你的回答:)
    • @Oktaytontaş 这是个问题吗?您使用reactjs 标签标记了问题。
    • 是的,因为 reactjs 开发人员通常都是了不起的开发人员,我认为他们可以提供帮助。你的回答太专业了,我很难理解
    • @Oktaytontaş 好的,我会留下我的答案以求繁荣,它可能会帮助其他人。在看到一些随机页面执行此操作后,我在同一条船上,想知道如何在我熟悉的技术中做同样的事情。我还想克服需要按钮来“添加新字段”的相同问题。如果您喜欢它,请随时为它投票。
    猜你喜欢
    • 2017-08-09
    • 1970-01-01
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    相关资源
    最近更新 更多