添加新的输入字段不会更新现有输入字段的值 [英] Adding new input field doesn't update the value of existing ones

查看:81
本文介绍了添加新的输入字段不会更新现有输入字段的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这就是它应该如何工作的.默认情况下,有两组输入字段,其中百分比字段的值分别为50%.现在,无论何时添加新的输入字段,都应在所有百分比字段之间分配百分比字段值,例如,如果有3组,则每个百分比字段应该具有33.33%.如果有4,则各占25%.现在,这部分工作正常.

现在,我正在尝试在其之上添加更多功能.我将简要地介绍这些功能以及与之相关的问题.

  1. 当用户单击percentage input field时,以前的值消失,用户键入一个新的百分比值,并在两个输入字段之间进行划分.但是问题在于它在用户刚刚输入的值的末尾添加了两个"%"符号.

  2. 第二个问题是,假设用户在第一个或第二个percentage field中键入新的百分比值,然后通过Add Field按钮添加新的input field,则百分比不会在所有输入值.新的input field没有考虑新的percentage value.我能想到的原因之一是percInput变量没有以某种方式更新.

  3. 第三个问题与第二个问题相似.如果用户先添加新的input field,然后在该新的input field中键入percentage value,则百分比值将完全不除.这也可能是因为percInput变量未更新.与此相关的另一个问题是,单击新的百分比输入字段不会像以前的默认字段一样删除先前的值.

  4. 这很奇怪.如果用户单击百分比输入字段,但未添加值,而是继续添加新字段,则百分比值将在所有百分比之间分配.

所有这些问题在某种程度上都是相互关联的,我感到它们都是由于一个变量,即percInput.我想添加新的输入字段时不会更新.以前,我使用calculatePercentage函数来更新percInput变量,在此起作用.但是当我在上述情况下尝试使用它时,它将不起作用.

这是我到目前为止尝试过的代码:

 const form = document.querySelector("form");
const span = document.querySelector("span");
const addBtn = document.querySelector("#addField");
const html = `
    <div class="url-pair">
        <input type="url" placeholder="3">
        <input type="text" class="perc">
        <button class="delete-btn" type="button">Delete</button>
    </div>
`;

// percentage variable and percentage calculation for the first time
let percInput = document.querySelectorAll('.urls-container .perc');
let percentage = (100 / percInput.length).toFixed(0).toString() + "%";

percInput.forEach((item) => {
    item.setAttribute("value", percentage);
});

const removeField = (e) => {
    if (!e.target.classList.contains('delete-btn')) return;
    e.target.parentElement.remove();
    calculatePercentage(); 
}

// percentage input variable update and percentage calculation
const calculatePercentage = () => {
    percInput = document.querySelectorAll('.urls-container .perc');
    percentage = (100 / percInput.length).toFixed(0).toString() + "%";

    percInput.forEach((item) => {
        item.setAttribute("value", percentage);
    });
}

// remove a field
form.addEventListener('click', removeField);

// add input field
addBtn.addEventListener('click', () => {
    span.insertAdjacentHTML("beforeBegin", html);
    calculatePercentage(); 
});


const percInputChange = function() {
    let val = this.value,
    $allInputs = $(percInput);

    if(val > 100) {
        $allInputs.val((100 / $allInputs.length) + "%");
        calculatePercentage();
    }else {
        $(percInput).not(this).val( (100 - val) / ($allInputs.length - 1) + "%");

        setTimeout(() => {
            this.value = this.value + "%";
        }, 500);

        calculatePercentage();

        return;
    }
};

// event listener when user types in a new percentage value
$( percInput ).on('keyup', percInputChange);

// event listener to hide previous input value
$( percInput ).focus(function() {
    this.value = "";
});

// event listener to divide the percetange values when the user clicks away
$( percInput ).blur(function() {
    if(this.value === ""){
        percInput.forEach(item => {
            item.value = ( 100 / percInput.length ).toFixed(0).toString() + "%";
            return;
        });
    }
}); 

 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="#" method="POST">

  <div class="urls-container">
    <div class="url-pair">
      <input type="url" placeholder="1">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <div class="url-pair">
      <input type="url" placeholder="2">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <span></span>
  </div>

  <div>
    <div>
      <button type="button" id="addField">Add Field</button>
    </div>

    <div>
      <button type="submit">Create</button>
    </div>
  </div>

</form> 

我知道这篇文章很奇怪,有很多问题.但是请耐心等待,因为我仍在学习中,如果我不将自己推入这些复杂的编码问题并陷入困境,我将无法学习.昨天我整天都在根据自己的知识尝试各种方法.如果我尝试使用所有方法,则帖子的篇幅会很大.所以,请忍受我.请帮助有需要的其他编码人员.谢谢

PS.我并没有同时使用jQuery和JS.但是,一旦解决问题,我将进行重构和更改. PS.

解决方案

我不太确定您要使用脚本真正实现什么目标.但是我可以通过删除冗余位来重新开始.以下代码段将允许您添加或删除输入行,并将相应地调整百分比.

也许您可以指定如何您希望脚本对任何用户输入做出反应?

 // add flields:
function addfields(){
   let all=$('.urls-container'), r=$('div:last',all).clone(),
       url=r.find('input[type=url]')[0];
   url.placeholder=+url.placeholder+1;
   $('.perc',r).removeAttr('data-manual');
   all.append(r); calcperc();
 }
// even distribution:
function calcperc(){
  let fix=$('.perc[data-manual]'),sum=0;
  fix.each(function(){sum+=parseFloat(this.value)});
  let rest= $('.perc').not(fix);
  rest.val(((100-sum)/rest.length).toFixed(2)+'%')
}

// manual distribution:
function recalc(){let inps=$('.perc'),cur=parseFloat(this.value);
 if (inps.length>1){
  this.value=cur.toFixed(2)+'%'; this.dataset.manual=1;
  calcperc();
} else this.value="100%"
}
// delegated event management:
$('form')
 .on('submit',function(e){e.preventDefault()}) // de-activate submit for testing
 .on('change','.perc',recalc)
 .on('click','.delete-btn',function(){$(this).parent().remove();calcperc()})
 .on('click','#addField',addfields);
 
 // initial distribution:
 calcperc(); 

 <script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<form action="#" method="POST">

  <div class="urls-container">
    <div class="url-pair">
      <input type="url" placeholder="1">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <div class="url-pair">
      <input type="url" placeholder="2">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <span></span>
  </div>

  <div>
    <div>
      <button type="button" id="addField">Add Field</button>
    </div>

    <div>
      <button type="submit">Create</button>
    </div>
  </div>

</form> 

我的当前版本的recalc()允许您覆盖百分比值的一个.然后将调整所有其他值,因此总和再次为100%.

还请注意,在我的版本中,recalc()是在input事件而不是keyup事件上触发的,否则添加百分号的操作将严重干扰用户的任何输入尝试./p>

修改
姓氏编辑涉及标记"或标记".在输入字段中使用data-manual属性手动更改百分比.这将保护该字段免受将来的重新计算.其余百分比将在非固定字段之间平均分配.

Here's how it's supposed to work. By default there are two sets of input fields where the percentage fields have a value of 50% each. Now whenever a new input field is added, the percentage field value should be divided between all of them, for example, if there are 3 sets then percentage fields should have 33.33% each. If there are 4 then 25% each. Now this part works perfectly fine.

Now I'm trying to add more features on top of it. I'll just explain the features in brief and the problem associated with it.

  1. When a user clicks on percentage input field, the previous value disappears and the user types a new percentage value and it gets divided between the two input fields. But the issue with this is it adds two "%" signs at the end of the value which the user just typed in.

  2. The second issue is, suppose the user types in a new percentage value in the first or second percentage field and then adds a new input field through Add Field button, the percentages doesn't divide between all the input values. The new input field doesn't take into consideration the new percentage value. One reason I could think of is the percInput variable doesn't get updated somehow.

  3. The third issue is similar to the second one. If the user adds a new input field first and then types in a percentage value in that new input field, then percentage values are not divided at all. This could also be because of percInput variable not being updated. Another issue associated with this is, clicking on the new percentage input field doesn't remove the previous value, like it does on the default fields.

  4. This is a weird one. If the user clicks on the percentage input field but doesn't adds a value and moves on to adding a new field, then the percentage values just divide between all of them.

All of these issues are somewhat related to each other and I have feeling a that they are all because of one variable, which is, percInput. I guess it doesn't get updated when new input fields are added. Previously I used calculatePercentage function to update the percInput variable, where it worked. But it doesn't work when I tried to use it in the situations above.

Here's the code I tried so far:

const form = document.querySelector("form");
const span = document.querySelector("span");
const addBtn = document.querySelector("#addField");
const html = `
    <div class="url-pair">
        <input type="url" placeholder="3">
        <input type="text" class="perc">
        <button class="delete-btn" type="button">Delete</button>
    </div>
`;

// percentage variable and percentage calculation for the first time
let percInput = document.querySelectorAll('.urls-container .perc');
let percentage = (100 / percInput.length).toFixed(0).toString() + "%";

percInput.forEach((item) => {
    item.setAttribute("value", percentage);
});

const removeField = (e) => {
    if (!e.target.classList.contains('delete-btn')) return;
    e.target.parentElement.remove();
    calculatePercentage(); 
}

// percentage input variable update and percentage calculation
const calculatePercentage = () => {
    percInput = document.querySelectorAll('.urls-container .perc');
    percentage = (100 / percInput.length).toFixed(0).toString() + "%";

    percInput.forEach((item) => {
        item.setAttribute("value", percentage);
    });
}

// remove a field
form.addEventListener('click', removeField);

// add input field
addBtn.addEventListener('click', () => {
    span.insertAdjacentHTML("beforeBegin", html);
    calculatePercentage(); 
});


const percInputChange = function() {
    let val = this.value,
    $allInputs = $(percInput);

    if(val > 100) {
        $allInputs.val((100 / $allInputs.length) + "%");
        calculatePercentage();
    }else {
        $(percInput).not(this).val( (100 - val) / ($allInputs.length - 1) + "%");

        setTimeout(() => {
            this.value = this.value + "%";
        }, 500);

        calculatePercentage();

        return;
    }
};

// event listener when user types in a new percentage value
$( percInput ).on('keyup', percInputChange);

// event listener to hide previous input value
$( percInput ).focus(function() {
    this.value = "";
});

// event listener to divide the percetange values when the user clicks away
$( percInput ).blur(function() {
    if(this.value === ""){
        percInput.forEach(item => {
            item.value = ( 100 / percInput.length ).toFixed(0).toString() + "%";
            return;
        });
    }
});

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="#" method="POST">

  <div class="urls-container">
    <div class="url-pair">
      <input type="url" placeholder="1">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <div class="url-pair">
      <input type="url" placeholder="2">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <span></span>
  </div>

  <div>
    <div>
      <button type="button" id="addField">Add Field</button>
    </div>

    <div>
      <button type="submit">Create</button>
    </div>
  </div>

</form>

I know this post is a weird one with so many problems. But please bear with me as I am still learning and I won't be able to learn if I don't push myself into these complex coding problems and get stuck. I've spent the whole day yesterday trying different methods based on the knowledge I have. The post would be really big if I put all the methods I tried. So please bear with me. Please help a fellow coder in need. Thanks

PS. I used jQuery and JS together which is not the right thing to do. But I will refactor and change them once I fix the issues. PS.

解决方案

I am not quite sure what exactly you want to achieve with your script. But I had a go at making a fresh start by removing redundant bits. The following snippet will allow you to add or remove input lines and it will adjust the percentages accordingly.

Maybe you can specifiy how you want the script to react on any user input?

// add flields:
function addfields(){
   let all=$('.urls-container'), r=$('div:last',all).clone(),
       url=r.find('input[type=url]')[0];
   url.placeholder=+url.placeholder+1;
   $('.perc',r).removeAttr('data-manual');
   all.append(r); calcperc();
 }
// even distribution:
function calcperc(){
  let fix=$('.perc[data-manual]'),sum=0;
  fix.each(function(){sum+=parseFloat(this.value)});
  let rest= $('.perc').not(fix);
  rest.val(((100-sum)/rest.length).toFixed(2)+'%')
}

// manual distribution:
function recalc(){let inps=$('.perc'),cur=parseFloat(this.value);
 if (inps.length>1){
  this.value=cur.toFixed(2)+'%'; this.dataset.manual=1;
  calcperc();
} else this.value="100%"
}
// delegated event management:
$('form')
 .on('submit',function(e){e.preventDefault()}) // de-activate submit for testing
 .on('change','.perc',recalc)
 .on('click','.delete-btn',function(){$(this).parent().remove();calcperc()})
 .on('click','#addField',addfields);
 
 // initial distribution:
 calcperc();

<script type="text/javascript" src="https://code.jquery.com/jquery-3.5.1.min.js"></script>

<form action="#" method="POST">

  <div class="urls-container">
    <div class="url-pair">
      <input type="url" placeholder="1">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <div class="url-pair">
      <input type="url" placeholder="2">
      <input type="text" class="perc">
      <button class="delete-btn" type="button">Delete</button>
    </div>

    <span></span>
  </div>

  <div>
    <div>
      <button type="button" id="addField">Add Field</button>
    </div>

    <div>
      <button type="submit">Create</button>
    </div>
  </div>

</form>

My curent version of recalc() allows you to overwrite one of the percentage values. All other values will then be adjusted, so the total is 100% again.

Please also note that in my version the recalc() gets fired on the input event and not the keyup event, otherwise the action of adding the percentage sign would seriously interfere with any input attempt by the user.

Edit
The lastet edit involves "marking" manually changed percentages with a data-manual attribute in the input field. This will protect that field from future recalculations. The remaining percentages will be distributed evenly among the non-fixed fields.

这篇关于添加新的输入字段不会更新现有输入字段的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆