JavaScript TypeError: Невозможно прочитать свойство 'id' из неопределенного - PullRequest
0 голосов
/ 13 декабря 2018

Предисловие:

У меня есть HTML-таблица, в которой пользователь заполняет Имя и URL-адрес социальных сетей, в которых он имеет учетную запись.В каждой строке есть флажок.С помощью jQuery и JavaScript при нажатии кнопки «Добавить строку» строка динамически добавляется в таблицу, а при нажатии кнопки «Удалить строку» удаляются те строки, для которых установлен флажок.

Цель:

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

Проблема:

Я не могу найти то, что заставляет его выдавать ошибку, поскольку childNodes[], кажется, не приводит к недоступному элементу.Пожалуйста, помогите!

Фрагмент:

    // variable to keep track of rows(records)
    var social_recs_num = 1;
    $(document).ready(function () {
    
      $("#social_add_rec").click(function () {
    
        social_recs_num++;
        var markup = "<tr> <th scope=\"row\"> <div class=\"form-group\"> <div class=\"form-check\"> <input type=\"checkbox\" class=\"form-check-input\" id=\"social_rec" + social_recs_num + "\" name=\"social_rec\"> <label class=\"form-check-label\" for=\"social_rec" + social_recs_num + "\"> " + social_recs_num + "</label> </div></div></th> <td> <div class=\"form-group shadow-sm\"> <label for=\"name_social" + social_recs_num + "\">Select or Type</label> <input type=\"text\" list=\"name_social" + social_recs_num + "\" class=\"form-control\" placeholder=\"Name\"> <datalist id=\"name_social" + social_recs_num + "\"> <option value=\"Wikipedia\">Wikipedia</option> <option value=\"Youtube\">Youtube</option> <option value=\"Facebook\">Facebook</option> <option value=\"Twitter\">Twitter</option> <option value=\"Pinterest\">Pinterest</option> </datalist> </div></td><td> <div class=\"form-group shadow-sm\"> <textarea class=\"form-control\" id=\"url_social" + social_recs_num + "\" cols=\"30\" rows=\"1\" placeholder=\"URL\"></textarea> </div></td></tr>"; //in case of id we need to do it like: "min_sysreq" +social_recs_num...as social_recs_num has been incremented priorly it will be the row number of row to be added
    
        $("table tbody").append(markup);
    
      });
    
      // Find and remove selected table rows...only condition is that there must be present attribute name='sysreq_rec' in input element for checkbox of every row
    
      $("#social_delete_rec").click(function () {
    
        $("table tbody").find('input[name="social_rec"]').each(function () {
    
          if ($(this).is(":checked")) {
            social_recs_num = social_recs_num - $(this).length;
            $(this).parents("tr").remove();
    
          }
    
        });
        // to be run when a row is deleted...this assigns ids to input elements in serial manner            
        var table = document.getElementById("mytab1");
        var rowCount = table.rows.length;
        
        // i has been initiated with 1, as header row is the 0th row
        for (var i = 1; i < rowCount; i++) {
          var row = table.rows[i];
    
          // on this line, getting error: `Uncaught TypeError: Cannot read property 'id' of undefined`
          row.childNodes[0].childNodes[0].childNodes[0].childNodes[0].id = "social_rec" + i;
          row.childNodes[0].childNodes[0].childNodes[0].childNodes[1].for = "social_rec" + i;
          row.childNodes[0].childNodes[0].childNodes[0].childNodes[1].innerHTML = " " + i;
    
          row.childNodes[1].childNodes[0].childNodes[0].for = "name_social" + i;
          row.childNodes[1].childNodes[0].childNodes[1].list = "name_social" + i;
          row.childNodes[1].childNodes[0].childNodes[2].id = "name_social" + i;
    
          row.childNodes[2].childNodes[0].childNodes[0].id = "url_social" + i;
    
          //iterate through rows
          //rows would be accessed using the "row" variable assigned in the for loop
    
        }
    
      });
    
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table table-bordered" id="mytab1">
      <thead>
        <tr>
          <th scope="col">
            #
          </th>
          <th scope="col">
            Name
          </th>
          <th scope="col">
            URL
          </th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <th scope="row">
            <div class="form-group">
              <div class="form-check">
                <input type="checkbox" class="form-check-input" id="social_rec1" name="social_rec">
                <label class="form-check-label" for="social_rec1"> 1</label>
              </div>
            </div>
          </th>
          <td>
            <div class="form-group shadow-sm">
              <label for="name_social1">Select or Type</label>
              <input type="text" list="name_social1" class="form-control" placeholder="Name">
              <datalist id="name_social1">
                <option value="Wikipedia">Wikipedia</option>
                <option value="Youtube">Youtube</option>
                <option value="Facebook">Facebook</option>
                <option value="Twitter">Twitter</option>
                <option value="Pinterest">Pinterest</option>
              </datalist>
            </div>
          </td>
          <td>
            <div class="form-group shadow-sm">
              <textarea class="form-control" id="url_social1" cols="30" rows="1" placeholder="URL"></textarea>
            </div>
          </td>
        </tr>
      </tbody>
    </table>
    <button class="btn btn-primary" type="button" id="social_add_rec">Add Row</button>
    <button class="btn btn-primary" type="button" id="social_delete_rec">Delete Row</button>

PS:

  1. Я использовал jQuery и Bootstrap.
  2. этот вопросказалось близким, но я думаю, что у меня нет той же ошибки.

Редактировать:

Мне нужно отобразить (или сохранить) вводимые пользователем данные, для которых я написал следующий JavaScriptcode.

var social = function () {

    var val = "social:\n";
    for (x = 1; x <= social_recs_num; x++) {
      //where social_recs_num is number of rows
      val = val + "\s\s-\n";
      val = val + "\s\s\s\s" + "name: " + getElementById("name_social" + x) + "\n";
      val = val + "\s\s\s\s" + "url: " + getElementById("url_social" + x) + "\n";
    }

    return val;

}

function social возвращает значение, введенное пользователем в формате YAML.Для этого кода при удалении выбранных строк я хочу назначить id элементам ввода и флажкам каждой оставшейся строки в последовательном порядке.

1 Ответ

0 голосов
/ 13 декабря 2018

Проблема:

Проблемы, с которыми вы сталкиваетесь, связаны с тем, что вы пытаетесь получить свойство childNodes элемента html.Чтобы получить доступ к этому свойству, вам нужно будет привести элемент к объекту jQuery, добавив вокруг него '$ ()'.В этом случае это будет $ (строка).

Однако, если вы сделаете это со своим кодом, вы все равно получите ошибки из-за путаницы вложенных .childNodes [0].Вы можете заставить его работать, используя этот существующий код, однако ...

Предлагаемый рефакторинг:

... Как уже говорилось, есть более изящные способы приблизиться к этомупроблема.Есть несколько способов, которыми вы могли бы заняться этим, но, учитывая ваш текущий html, я бы перестроил что-то вроде этого:

//...


// to be run when a row is deleted...this assigns ids to input elements in serial manner                
$('#mytab1 tbody tr').each(function() {
    var rowNum = $(this)[0].rowIndex;

    var formcheck = $(this).find('.form-check');  
    formcheck.find('.form-check-input')[0].id = 'social_rec' + rowNum;
    formcheck.find('.form-check-label')[0].for = 'social_rec' + rowNum;
    formcheck.find('.form-check-label')[0].innerHTML = ' ' + rowNum;

    var formName = $(this).find('td')[0];
    $(formName).find('label')[0].for = 'social_rec' + rowNum;
    $(formName).find('input')[0].list = 'social_rec' + rowNum;
    $(formName).find('datalist')[0].id = 'social_rec' + rowNum;

    var formUrl = $(this).find('td')[1];
    $(formUrl).find('textarea')[0].id = 'social_rec' + rowNum;          
});


//...

Это заменит ваш цикл for на цикл jquery .each, а затем использует .find.() функция для зацикливания каждого элемента управления, которым вы хотите манипулировать.Вы также заметите, что она использует функцию rowIndex () для определения того, какой номер назначать строке.

Я думаю, что преимущество такого подхода в том, что намного проще читать код и определятькакие элементы управления затрагиваются.Вы также можете дополнительно реорганизовать свой html, чтобы использовать классы, которые являются уникальными для элементов управления, на которые вы хотите настроить таргетинг, затем вы можете просто использовать селектор классов, чтобы изменить эти элементы управления.

Надеюсь, это поможет!

...