Arhn - архитектура программирования

Как извлечь данные HTML-формы с помощью javascript?

Мне нужно извлечь данные из формы HTML с помощью javascript (+ Mootools) в том же формате вложенного объекта, который PHP увидит при публикации формы.

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

Я попробовал serializeArray с jsFiddle http://jsfiddle.net/7quxe/, и результаты меня разочаровали.

Ранее я сам написал сценарий для этого, и он работал довольно хорошо, за исключением некоторых проблем, когда в форме были перекрывающиеся поля смешанного типа ключа (<input name="foo[bar]" value="1"> and <input name="foo[]" value="2". Я уже начал работать над лучшей версией, но когда я обнаружил, что начинаю заново И снова я подумал про себя: существует множество отличных js-библиотек, которые нацелены на решение многих основных повседневных проблем, неужели желание извлечь данные из формы в правильно отформатированный объект не так уж распространено?

Вот пример того, что я пытаюсь:

<form method="post" action="/">
    <input name="test" value="test">
    <input name="nested[a]" value="a">
    <input name="nested[b]" value="b">
    <input name="nested[c]" value="c">
    <input name="arraytest[]" value="foo">
    <input name="arraytest[]" value="foo">
    <input name="arraytest[]" value="foo">
</form>

Вот как PHP увидит это:

$_POST = array(
    'test' => 'test',
    'nested' => array(
        'a' => 'a',
        'b' => 'b',
        'c' => 'c',
    ),
    'arraytest' => array(
        0 => 'foo1',
        1 => 'foo2',
        2 => 'foo3'
    )
)

и это то, что я хотел бы получить в js:

{
    test : 'test',
    nested : {
        a : 'a',
        b : 'b',
        c : 'c'
    },
    arraytest : {       // This could also be an array ['foo1','foo2','foo3']
        0 : 'foo1',
        1 : 'foo2',
        2 : 'foo3'
    }
}
16.11.2012

  • взгляните на этот stackoverflow.com/questions/2192091/ 16.11.2012
  • @Kotzilla Я знаю, как получить доступ к значениям отдельно. Проблема здесь в том, чтобы поместить их в чистый и правильно вложенный объект. Смотрите редактирование. 16.11.2012

Ответы:


1
FormData data= new FormData();

Данные состоят из всех ваших данных формы. Если вы хотите конкретно, вам нужно использовать

data.get("fieldName");
27.07.2018

2

Вы можете сделать это с помощью прямого JavaScript, используя объект form.elements. Вот пример, который преобразует любую форму в строку параметров URL:

function getParameters(form) {
  var parameters = "";
  for (var x=0, y=form.elements.length; x < y; x++) {
  var field = form.elements[x];
  if (field.name && field.type !== "submit") {
    parameters += "&" + encodeURIComponent(field.name) + "=" + (field.type == "radio" || field.type == "checkbox" ? (field.checked == "checked") : encodeURIComponent(field.value));
  }
  return parameters;
}
16.11.2012

3

из вашего ответа. я сделал скрипт jquery для извлечения элемента ввода, и он будет работать только с входным одномерным массивом, таким как «input [string]» и «input []», ура
jsfiddle

HTML

<h2>Form</h2>
<form action="" name="form" method="post">
  <input name="test" value="test">
  <input name="nested[a]" value="a">
  <input name="nested[b]" value="b">
  <input name="nested[c]" value="c">
  <input name="arraytest[]" value="foo">
  <input name="arraytest[]" value="foo">
  <input name="arraytest[]" value="foo">
  <p><input type="submit" /></p>
</form>

<h2>JSON output</h2>
<pre id="result"></pre>​​​​​​

JQuery

  $.fn.serializeObject = function()
  {
    var o = {}, a = this.serializeArray();
    $.each(a, function() {

      if (/(\[\]$|\[.+\]$)/.test(this.name)) {

        var match = /(.+)(\[\]|\[(.+)\])/.exec(this.name);
        if (match[3] !== undefined)
        {
          var index = match[3];
          if (o[match[1]] === undefined)
            o[match[1]] = {};

          if (o[match[1]][index] === undefined)
            o[match[1]][index] = [o[match[1]][index]];

          o[match[1]][index] = this.value || '';

        } else {
          if (o[match[1]] === undefined)
            o[match[1]] = new Array;

          o[match[1]].push(this.value || '');
        }


      } else {
        if (o[this.name] !== undefined) {
          if (!o[this.name].push) {
            o[this.name] = [o[this.name]];
          }
          o[this.name].push(this.value || '');
        } else {
          o[this.name] = this.value || '';
        }
      }

    });

    return o;
  };

  $(function() {
    $('form').submit(function() {
      $('#result').text(JSON.stringify($('form').serializeObject()));
      return false;
    });
  });​
16.11.2012
  • Спасибо за ваши усилия. К сожалению, я не использую jQuery и доделал свою версию. Это довольно аккуратно, поэтому, если хотите, проверьте мой ответ через минуту. Тем не менее, +1 за ваши усилия :) 16.11.2012

  • 4

    Я был одержим этим, а потом еще :D

    Вот мое решение: http://jsfiddle.net/sLZZr/3/

    Не стесняйтесь брать его. Если вы найдете это полезным, дайте мне знать (не требование, просто любопытно. Мой адрес электронной почты находится в источнике :)


    Для ответа требуется отформатированный код, поэтому вот:

    /**
     * FormAccess
     * 
     * @description Manipulate data in forms and element collections. Currently only reading supported.
     *
     * @version     0.8
     *
     * @license     MIT License
     * 
     * @author      Jani Peltoniemi <[email protected]>
     * 
     * @copyright   2012 Jani Peltoniemi
     */
    
    
    /**
    * FormAccess main class
    * 
    */
    FormAccess = new Class({
        formElm : null,                 // The form element this instance will be linked to
        /**
        * Constructs the class and adds the quick access method "extractData" to formElm
        * 
        * @param Form element
        */
        initialize:function(formElm) {
            this.formElm = document.id(formElm);
            this.formElm.extractData = this.extractData.bind(this);
        },
        /**
        * Calls the static extractData function with the linked form's inputs
        * 
        * @returns Extracted form data in nested object
        */
        extractData : function() {
            var inputElms = this.formElm.getElements('input,textarea,select');
            return this.$constructor.extractData(inputElms);    
        }
    
    });
    
    /**
    * FormAccess static functions
    * 
    * Currently only reading available. Filling forms according to data in an object will come later.
    * 
    */
    FormAccess.extend({
        /**
        * Extracts the data from given elements
        * 
        * Notes :
        *   - Converts empty keys to numeric. If (non-converted)numeric keys are already present, empty key becomes <largest key>+1.
        *       - Elements are handled from top to bottom. When converting empty keys between other numeric keys the largest key means largest key _up to that point_.
        *   - Inputs with empty names are not included in results.
        *   - Checkboxes' value attribute is ignored and only their checked state is included in results.
        *   - Multi-selectboxes return the selected values in an array
        * 
        * @param Selector, element or element collection - everything that $$() takes in.
        * 
        * @returns Extracted form data in nested object
        */
        extractData : function(inputElms) {
            // Normalize the input / query DOM
            inputElms = $$(inputElms);
    
            var that = this;
            var result = {};
    
            // Data from input elements is collected here for easier handling
            var inputData = [];
    
            // Collect inputData
            inputElms.each(function(inputElm) {
                if (!inputElm.name)
                    return;
                // Explode the input name into an array path
                var path = that.parseName(inputElm.name);
    
                inputData.push({
                    path:path,
                    value:inputElm.value ? inputElm.value : '',
                    elm:inputElm
                });
            });
            // Index tracking variable. Used to find next free numeric keys
            var maxIndex;
            inputData.each(function(data,i) {
                var path = data.path;
    
                // Last element of the path needs special treatment. Pop it out.
                var last = path.pop();
    
                // Working var
                var current = result;
    
                path.each(function(part) {
    
                    // Assign a numeric key if the key is empty
                    if (part == '') {
                        // Reset the index tracker
                        maxIndex = -1;
    
                        // Loop through the current position in result set
                        Object.each(current,function(val,key) {
                            // Convert key to int and make sure it is a proper number
                            var intKey = key.toInt();
                            if (intKey == key && intKey > maxIndex) {
                                // Key is greater than known largest key.
                                maxIndex = intKey;
                            }
                        });
                        // Set the key to largest found key + 1
                        part = maxIndex + 1;
                    }
    
                    // If the next position is not defined or is not an object, overwrite it.
                    if (typeOf(current[part]) != 'object')
                        current[part] = {};
    
                    // Update the position
                    current = current[part];
                });
    
                var lastWasEmpty = false;
                // Evaluate the last part separately
                if (last == '') {
                    lastWasEmpty = true;
                    // Reset the index tracker
                    maxIndex = -1;
    
                    // Loop through the current position in result set
                    Object.each(current,function(val,key) {
                        // Convert key to int and make sure it is a proper number
                        var intKey = key.toInt();
                        if (intKey == key && intKey > maxIndex) {
                            // Key is greater than known largest key.
                            maxIndex = intKey;
                        }
                    });
                    // Set the key to largest found key + 1
                    last = maxIndex + 1;
                }
    
                // Element-specific value handling
                switch (data.elm.tagName.toLowerCase()) {
                    // Case for Select, since they allow multiple selections
                    case 'select':
                        if (data.elm.multiple) {
                            // A <value> = <selected> format was considered here but rejected due to long values being bad keys
                            current[last] = data.elm.getSelected().get('value');
                        } else
                            current[last] = data.value; 
                    break;
    
                    // Inputs have a couple of special cases that need to be handled differently
                    case 'input':
                        switch (data.elm.type) {
                            // Only the value of the checked radiobutton is included in results.
                            // If none is checked, the result will display null
                            case 'radio':
                                // Only set the value if radiobutton is checked
                                // Otherwise check if this key is not already in results and then set it to null
                                if (data.elm.checked)
                                    current[last] = data.value; 
                                else if (current[last] == undefined)
                                    current[last] = null;
                            break;
    
                            // Checkboxes' value attribute is ignored and the checked state is included in results
                            case 'checkbox':
                                current[last] = data.elm.checked;
                            break;
    
                            // All others
                            default:
                                    current[last] = data.value; 
                            break;
                        }
                    break;
    
                    // All other elements are handled here. 
                    default:
                        current[last] = data.value; 
                    break;
                }
            });
            return result;
        },
        /**
        * Explodes the name attribute.
        * 
        * Example:
        *   name="testinput[foo][bar][]"  -> ['testinput','foo','bar','']
        * 
        * @param Input name
        * 
        * @returns Exploded input name
        */
        parseName : function(name) {
            var path = [name.match(/^[^\[]*/)[0]];
            var pathRegExp = /\[(.*?)\]/g;
            var part = '';
            while (true) {
                part = pathRegExp.exec(name);
                if (part !== null)
                    path.push(part[1]);
                else
                    break;
            }
    
            return path;
        },
        /**
        * Applies the FormData object to chosen form elements.
        * 
        * If falsy argument is given, FormData is applied to all forms
        * 
        * @param Selector, element or element collection - everything that $$() takes in.
        * 
        * @returns Element collection
        */
        apply : function(elements) {
            if (!elements)
                elements = 'form';
            elements = $$(elements);
    
            elements.each(function(element) {
                element.formAccess = new FormAccess(element);
            });
    
            return elements;
        }
    });
    
    16.11.2012

    5

    В dojo есть удобный метод для этого, который называется dojo. .formToObject(). Как следует из названия, он преобразует все элементы формы (ввод, выбор, ...) в объект. Затем вы можете легко преобразовать его в JSON и отправить по сети, например, через AJAX.

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

  • 6
    export default class Article extends Component{
        handlesubmit(e)
        {
            e.preventDefault();
            const data = new FormData(e.target);
            let userid=qs.parseUrl(window.location.search).query.id;
            data.append("userid",userid);
            if(document.cookie.split(';')[0]=='login=true')
            fetch('/api/medium/article',{
                method: 'POST',
                body:data
            })
            .then(Response=>{
                console.log(Response);
                return Response.json();
            })
            .then(Response=>{
                console.log(Response);
                window.location.pathname='/medium';
                return Response;
            })
            .catch(err=>{
                return err;
            });
            else{
                alert("please login again");
                window.location.pathname='/medium';
            }
        }
        render()
        {
            return (
                <div className="create-article">
                    <form encType="multipart/form-data" className="articleCreating" onSubmit={this.handlesubmit} >
    
                        <div className="form-group">
                            <select className="custom-select" autoFocus required name='category'>
                                <option value="">Select Category</option>
                                <option value="TECHNOLOGY">Technology</option>
                                <option value="NATURE">Nature</option>
                                <option value="FOOD">Food</option>
                            </select>
                        </div>
    
                        <div className="input-group">
                            <input type="text" className="form-control" aria-label="Title" placeholder="Title"
                            maxLength="70" spellCheck="true" name="title" required />
                        </div>
    
                        <div className="input-group">
                            <input type="text" className="form-control" aria-label="Subtitle" placeholder="Subtitle" 
                            spellCheck="true" name="description" required />
                        </div>
    
                        <div className="input-group has-error">
                            <textarea className="form-control" aria-label="With textarea" placeholder="Description" cols="10"
                            rows="10" spellCheck="true" name="article" required>
                            </textarea>
                        </div>
    
                        <div className="fileinput">
                            <span><input type="file" name="image"/></span>
                        </div>
                        <div className="article-submit">
                           <button className="btn btn-raised btn-success" type='submit'>Create Article</button>
                        </div>
                    </form>
                </div>
    
            )
        }
    }
    

    это в реакции, я думаю, вы можете добиться того же, используя js

    27.07.2018
    Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..