Генерация динамических идентификаторов в элементах HTML с помощью jQuery - PullRequest
0 голосов
/ 25 марта 2019

Я встроен в генератор веб-резюме, чтобы научиться разрабатывать для веб-сайтов.Я создал HTML-форму, в которую пользователь может добавить больше полей, чтобы добавить больше информации о нем.Пример: у него более одного профессионального опыта, но форма начинается с одного поля prof-exp для заполнения.Поэтому он нажимает кнопку «Добавить новый опыт», и JS создает для нее новое поле.Для этого я использовал метод clone() из jQuery, но это дает мне проблемы, перечисленные ниже.Кроме того, вот код, который я сделал:

var index = 0;
$(document).ready(() => {
    $("#add-exp").click(() => {
        $("#professional").clone().attr("id", "professional" + index++).
        appendTo("#professional-info").find("select, input, textarea").val("");
    })
})
<!DOCTYPE html>
<html>


<body>

<form action="" method="GET" id="main">
  <fieldset id="professional-info">
                <legend><h2>professional experience</h2></legend>
                <div id="professional">
                    <label for="level">Nível: <select name="level" id="level" >
                        <option value="empty">Selecione</option>
                        <option value="estagio">Estágio</option>
                        <option value="junior-trainee">Junior/Trainee</option>
                        <option value="aux-opera">Auxiliar/Operacional</option>
                        <option value="pleno">Pleno</option>
                        <option value="senior">Sênior</option>
                        <option value="sup-coord">Supervisão/Coordenação</option>
                        <option value="gerencia">Gerência</option>
                    </select></label>
                    <label for="position"> Cargo: <input type="text" name="carrer" id="carrer" ></label><br>
                    <label for="company"> Empresa: <input type="text" name="company" id="company" ></label><br>
                    <label for="begin"> Início: <input type="month" name="begin" id="begin" ></label>
                    <label for="break"> Término: <input type="month" name="break" id="break" ></label>
                    <label for="stl-work"><input type="checkbox" name="stl-work" id="stl-work" >Ainda trabalho aqui</label><br>
                    <label for="job-desc"> Descrição: <textarea name="job-desc" id="job-desc"  placeholder="Conte um pouco sobre o que você fazia lá." cols="40" rows="1"></textarea></label>
                    <button type="button" id="remove-exp" >Remove this professional xp</button>
                </div>
                <button type="button" form="main" id="add-exp">Add other professional exp</button> 
            </fieldset>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</body>
</html>

Проблемы:

  • Только у div есть динамические идентификаторы, что вызывает у меня следующие две другие проблемы;

  • Я не знаю, как реализовать логику кнопки удаления, поскольку я не могу отличить 1-ю кнопку от других элементов Div *; 1018 *

  • Поскольку метки используют соответствующий идентификатор ввода для ссылки, когда пользователь щелкает его, они указывают на первые поля ввода;

Я надеюсь, что вы, ребята, могли понять мою проблемуи помоги мне с этим.Кроме того, извините за мой английский - я тоже учусь.Спасибо вам всем!

Ответы [ 4 ]

0 голосов
/ 25 марта 2019

Подробности демонстрационного кода комментируются в самом коде. В некоторые классы внесены незначительные изменения для <fieldset> с и <button> с. Структура немного изменена, так что имейте это в виду. jQuery универсален и позволяет вам обобщать операции DOM и избавляться от зависимости от идентификаторов - очень просто использовать классы.

События, зарегистрированные в динамических тегах, завершаются ошибкой, если вы не делегировали события. Чтобы делегировать событие щелчка всем кнопкам, существующим в настоящее время и в будущем, зарегистрируйте тег предка, которым обычно пользуются кнопки (например, #main). Затем назначьте селекторам кнопок второй параметр (данные события):

$('#main').on('click', '.add, .remove', function(e) {...  

Что касается удаления с помощью вложенной кнопки - $(e.target) и $(this) могут использоваться для ссылки на кнопку, которая была нажата в данный момент. Когда вам нужно найти подходящего предка для нажатой кнопки (например, .professional), используйте метод .closest(), например, так:

$(e.target).closest('.professional').remove();

Демо

let index = 0;
// Hide the first .remove button
$('#remove').hide();
/*
Register the form to the click event 
Event data directs .add and .remove buttons
*/
$("#main").on('click', '.add, .remove', function(e) {
  // if the clicked button has .add
  if ($(this).hasClass('add')) {
    /*
    clone the first .professional
    increment counter
    Reference all form controls of the clone
    on each form control modify its id 
    */
    const dupe = $(".professional:first").clone(true, true);   
    index++;
    const formControls = dupe.find('select, button, input, textarea');
    formControls.each(function() {
      let ID = $(this).attr('id');
      $(this).attr('id', ID + index);
    });
    
    /*
    Remove the legend from clone
    Show the .add and .remove on clone
    Hide the clicked button
    Add clone to form
    Stop event bubbling
    */
    dupe.find('legend').remove();
    dupe.find('.add, .remove').show();
    $(e.target).hide();
    $('#main').append(dupe);
    e.stopPropagation();
  // Otherwise if clicked button has .remove...  
  } else if ($(e.target).hasClass('remove')) {
    /*
    Find clicked button ancestor .professional and remove 
    it.
    Hide all .add buttons
    Show the last .add
    Stop event bubbling
    */
    $(e.target).closest('.professional').remove();
    $('.add').hide();
    $('.add:last').show();
    e.stopPropagation();
    
  } else {
    // Otherwise just stop event bubbling
    e.stopPropagation();
  }
});
:root {
  font: 400 14px/1 Consolas
}

fieldset {
  width: fit-content
}

legend {
  margin-bottom: -15px
}

label {
  display: block
}

input,
select,
button {
  display: inline-block;
  font: inherit;
  height: 3ex;
  line-height: 3ex;
  vertical-align: middle
}

.text input {
  width: 24ch
}

select {
  line-height: 4ex;
  height: 4ex;
}

label b {
  display: inline-block;
  width: 7.5ch;
}

button {
  position: absolute;
  display: inline-block;
  height: initial;
  margin: 0;
}

.add {
  position: absolute;
  right: 0;
}

[for=level] b {
  width: 6ch
}

.btn-grp {
  position: relative;
  width: 97%;
  min-height: 26px;
  padding: 0
}
<!DOCTYPE html>
<html>

<head></head>

<body>
  <form action="" method="GET" id="main">
    <fieldset class="professional">
      <legend>
        <h2>Professional Experience</h2>
      </legend>
      <label for="level">
          <b>Nível: </b>
          <select name="level" id="level">
            <option value="empty">Selecione</option>
            <option value="estagio">Estágio</option>
            <option value="junior-trainee">
              Junior/Trainee
            </option>
            <option value="aux-opera">
              Auxiliar/Operacional
            </option>
            <option value="pleno">Pleno</option>
            <option value="senior">Sênior</option>
            <option value="sup-coord">
              Supervisão/Coordenação
            </option>
            <option value="gerencia">
              Gerência
            </option>
          </select>
        </label>
      <fieldset class='text'>
        <label for="carrier"><b>Cargo: </b> 
          <input type="text" name="carrer" id="carrer">
          </label>
        <label for="company"><b>Empresa: </b>
          <input type="text" name="company" id="company">
          </label>
        <label for="begin"><b>Início: </b> 
          <input type="month" name="begin" id="begin">
          </label>
        <label for="break"><b>Término: </b> 
          <input type="month" name="break" id="break">
          </label>
      </fieldset>
      <label for="stl-work">
        <input type="checkbox" name="stl-work" id="stl-work" >Ainda trabalho aqui
        </label>
      <label for="job-desc"><b>Descrição: </b></label>
      <textarea name="job-desc" id="job-desc" placeholder="Conte um pouco sobre o que você fazia lá." cols="35" rows="1"></textarea>
      <fieldset class='btn-grp'>
        <button type="button" id='remove' class='remove'>Remove</button>
        <button type="button" id='add' class="add">Add</button>
      </fieldset>
    </fieldset>
  </form>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</body>

</html>
0 голосов
/ 25 марта 2019

Один из способов связать вашу новую кнопку «удалить» с ее «профессиональным» div - это добавить дополнительный оператор в ваш обработчик событий, чтобы обновить его идентификатор параллельно идентификатору нового div, что-то вроде:

let lastIndex = index - 1;
$("#professional" + lastIndex).find("button").attr("id", "add-exp" + lastIndex);

(Этот код может иметь неправильный синтаксис - я не очень часто использую jQuery - но вы можете понять идею.)

Лучше может быть, когда нажата кнопка «удалить», не удаляйте в соответствии с идентификатором, а вместо этого найдите ближайший предок div и удалите этот div.

Для ярлыков вы должны пропустить id s (потому что никакие два элемента на одной странице не должны иметь одинаковые id). А поскольку входные данные вложены в метки, вы также должны иметь возможность пропустить атрибут for и позволить ассоциации быть неявной. (См. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label.)

0 голосов
/ 25 марта 2019

Как и предполагалось, Vue.js - это круто, но jQuery тоже обладает некоторыми забытыми способностями.

И, поскольку вы создаете элементы динамически, не использует идентификаторы.
И отправьте бэкенду свои опыты в виде массивов []: т.е.: name="carrer[]", name="company[]" и т. Д. Затем в бэкэнде зациклите эти массивы данных, чтобы получить все пользовательские взаимодействия.

const new_exp = () => $('<div>', {
  'class': 'professional-exp',
  html: `
       <label>Nível:
         <select name="level[]">
           <option value="empty">Selecione</option>
           <option value="estagio">Estágio</option>
           <!-- etc... -->
         </select>
      </label>
      <label>Cargo: <input type="text" name="carrer[]"></label><br>
      <label>Empresa: <input type="text" name="company[]"></label><br>
      <label>Início: <input type="month" name="begin[]"></label>
      <label>Término: <input type="month" name="break[]" ></label>
      <label><input type="checkbox" name="stl-work[]"> Ainda trabalho aqui</label><br>
      <label>Descrição: <textarea name="job-desc[]" placeholder="Conte um pouco sobre o que você fazia lá." cols="40" rows="1"></textarea></label><br>
     `,
  append: $('<button>', {
    type: 'button',
    text: 'Remove',
    click() {
      $(this).closest('.professional-exp').remove();
    }
  }),
  appendTo: '#professional',
});


jQuery($ => { // DOM ready and $ alias in scope

  new_exp();                          // On init (Create first exp)
  $("#new_exp").on('click', new_exp); // On click

});
.professional-exp {
  padding: 10px;
  margin-bottom: 10px;
  background: #eee;
}
<form action="" method="POST" id="main">
  <fieldset>
    <legend>
      <h2>Professional experience</h2>
    </legend>
    <div id="professional"></div>
    <button type="button" id="new_exp">+ Add more</button>
  </fieldset>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Выше мы определяем действие кнопки «Удалить» прямо в шаблоне, но при желании вы также можете жестко закодировать кнопку в шаблон и создать динамический обработчик кликов (используя jQuery .on()), например:

const exp_new = () => $('<div>', {
  'class': 'professional-exp',
  html: `
     <label>Nível:
       <select name="level[]">
         <option value="empty">Selecione</option>
         <option value="estagio">Estágio</option>
         <!-- etc... -->
       </select>
    </label>
    <label>Cargo: <input type="text" name="carrer[]"></label><br>
    <label>Empresa: <input type="text" name="company[]"></label><br>
    <label>Início: <input type="month" name="begin[]"></label>
    <label>Término: <input type="month" name="break[]" ></label>
    <label><input type="checkbox" name="stl-work[]"> Ainda trabalho aqui</label><br>
    <label>Descrição: <textarea name="job-desc[]" placeholder="Conte um pouco sobre o que você fazia lá." cols="40" rows="1"></textarea></label><br>
    <button class="exp_delete">REMOVE</button>
  `,
  appendTo: '#professional',
});



jQuery($ => { // DOM ready and $ alias in scope

  exp_new();                          // On init (Create first exp)
  $("#exp_new").on('click', exp_new); // and on click.
  $('#main').on('click', '.exp_delete', ev => $(ev.target).closest('.professional-exp').remove());

});
.professional-exp {
  padding: 10px;
  margin-bottom: 10px;
  background: #eee;
}
<form action="" method="POST" id="main">
  <fieldset>
    <legend>
      <h2>Professional experience</h2>
    </legend>
    <div id="professional"></div>
    <button type="button" id="exp_new">+ Add more</button>
  </fieldset>
</form>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
0 голосов
/ 25 марта 2019

, если вы уже заключили свой ввод в метку, вам больше не нужен идентификатор, и вы можете использовать this в качестве параметра кнопки удаления, чтобы вы могли использовать его для удаления своего блока.

Пожалуйста,проверьте следующий пример

$(function(){
	// keep the first block hidden as an empty template 
	$('.form-row:first').hide();
	// trigger add new item
	AddItem();
})
function AddItem(){
	var container = $('#container');
	// clone the form, show it & append before add button
	var cloned = $('.form-row:first').clone().show().insertBefore($('#addBtn'));
}
function RemoveItem(elm){
	// get form element & remove it
	$(elm).closest('.form-row').remove()
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<style type="text/css">
.form-row {border:1px solid #ccc; margin:5px 0;padding:10px;}
</style>
<div id="container">
	<div class="form-row">
		<!-- wrap your input inside label tag to avoid using id as reference -->
		<label>Field 1 : <input type="text" name="field1"></label>
		<label>Field 2 : <input type="text" name="field2"></label>
		<input type="button" value="Remove this item" onclick="RemoveItem(this)">
	</div>
	<input id="addBtn" type="button" value="Add new item" onclick="AddItem()">
</div>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...