Правильно Заменить значения автозаполнения ключом перед публикацией

Я использую HandsOnTable, чтобы сделать редактирование таблиц базы данных более интерактивными на моем сайте.

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

В пользовательском интерфейсе я бы хотел, чтобы эти столбцы отображались в виде раскрывающихся меню, где пользователь выбирает читаемое значение, сопоставленное с ранее упомянутым внешним ключом (т.е. что-то вроде select имени/значения HTML).

К сожалению, у HandsOnTable такой тип ячейки нет. Самое близкое к этому - autocomplete. Это позволяет мне создать выпадающий список, но он содержит только значения; нет соответствующих клавиш. Вот как он создается:

"source": ["Jebediah", "Bob", "Bill", "Buzz"]

Поэтому я планирую отправить две строки Json с сервера:

Один, содержащий параметры, необходимые HandsOnTable для визуализации таблицы:

{
    "data": [
        { "ID": 1, "Description": "Crude", "Volume": 204, "Customer": "jebediah" },
        { "ID": 2, "Description": "Hidrogen", "Volume": 513, "Customer": "Bob" },
        { "ID": 3, "Description": "Coal", "Volume": '67', "Customer": "Bill" },
        { "ID": 4, "Description": "Wood", "Volume": '513',  "Customer": "Buzz" }
    ],
    "columns": [
        { "data": "ID", "type": "numeric" },
        { "data": "Description", "type": "text"},
        { "data: "Volume", "type": "numeric" },
        { "data": "color", "type": "autocomplete", "strict": "true",
            "source": ["Jebediah", "Bob", "Bill", "Buzz"]}
    ]
}

Второе отображение ключей к значениям

{
    "mappings": [
        {"key": 0, "value": "Jebediah"}, 
        {"key": 0, "value": "Bob"},
        {"key": 0, "value": "Bill"}, 
        {"key": 0, "value": "Buzz"}
    ]
}

Все идет нормально. Теперь для сложной части:

Функция HandsOnTable имеет функцию (getData()), которая позволяет мне извлекать данные таблиц в виде строки Json, готовой к отправке на сервер:

var jdata = myHandsOnTable.getData();

Где jdata будет выглядеть примерно так:

"data": [
    { "ID": 1, "Description": "Crude", "Volume": 204, "Customer": "jebediah" },
    { "ID": 2, "Description": "Hidrogen", "Volume": 513, "Customer": "Bob" },
    { "ID": 3, "Description": "Coal", "Volume": '67', "Customer": "Bill" },
    { "ID": 4, "Description": "Wood", "Volume": '513',  "Customer": "Buzz" }
]

Теперь перед публикацией я хотел бы заменить эти значения для узла Customer их соответствующим парным ключом в строке japp mappings.

Как я могу достичь этого в JavaScript/JQuery?

Есть ли функция, которая работает что-то следующим образом:

jdata.replaceNode('node', mappings)

благодаря

Ответ 1

У меня была аналогичная проблема, и вот что я сделал...

Для каждого столбца внешнего ключа я сохранил 2 значения в режиме handsontable; один для самого идентификатора, который я устанавливаю как скрытый столбец, а другой - удобное для чтения текстовое значение в виде выпадающих меню.

Каждый раз, когда изменяется значение выпадающего списка, я также изменяю соответствующий скрытый идентификатор. В моем случае у меня есть раскрывающийся список за пределами handsontable в качестве фильтра, который я использую для сопоставления пар ключ/значение, но вы можете использовать Hashtables или что-то еще.

Теперь код...

Удобная конфигурация:

afterChange: function (changes, source) { AfterChange(changes, source); }

После события изменения (каждый раз, когда в таблице происходит изменение):

function AfterChange(Changes, Source) {

    if (Source === 'loadData') {
        return; //don't save this change
    }
    var rowIndex = 0, columnID = 1, oldTextVal = 2, newTextVal = 3, ntv = '', nv = '';
    $(Changes).each(function () {
        if (this[columnID] === 'CategoryID') {
            // Do nothing...
            //To make sure nothing else happens when this column is set through below
        }
        else if (this[columnID] === 'CategoryName') {
            ntv = this[newTextVal];
            //This is where I do my mapping using a dropdown.
            nv = $('#CategoriesFilterDropdown option').filter(function () { return $(this).text() === ntv; }).val();
            //13 is my CategoryID column
            $container.handsontable('setDataAtCell', this[rowIndex], 13, nv);
        }
    });
    }
}

Таким образом, вы меняете внешние ключи так, как вам, и вам не нужно перебирать все это до сохранения. Это также упрощает отправку данных таблицы, как и обратно на сервер.

Таким образом,

  • Пользователь взаимодействует с столбцом CategoryName (который имеет autocomplete типа).
  • CatgoryID скрыт для пользователя, установив ширину столбца на 0, используя параметр colWidths для handsontable.
  • Когда поле CategoryName изменяется, используйте событие afterChange для установки соответствующего столбца CategoryID. В моем случае я использую раскрывающийся список где-то еще на странице, чтобы сопоставить Name => ID, но вы можете использовать другие средства, такие как хеш-таблица.

Надеюсь, это имеет смысл...

Ответ 2

jExcel - альтернативный плагин для handsontable, который имеет полную поддержку для k => v выпадающих списков. Более продвинутое демо с использованием условных опций в раскрывающемся списке можно найти по адресу: http://jsfiddle.net/orz8frko/3/

data = [
    [3, 'Cheese'],
    [1, 'Apples'],
    [2, 'Carrots'],
    [1, 'Oranges'],
];

$('#my').jexcel({
    data:data,
    colHeaders: ['Model','Color'],
    colWidths: [ 300, 80 ],
    columns: [
        { type: 'dropdown', source:[
            {'id':'1', 'name':'Fruits'},
            {'id':'2', 'name':'Legumes'},
            {'id':'3', 'name':'General Food'}]
        },
        { type: 'text' },
    ]
});
body { background-color:#eee }
<link rel="stylesheet" type="text/css" href="#" onclick="location.href='https://bossanova.uk/components/bossanova-ui/css/jquery.jexcel.css'; return false;">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="https://bossanova.uk/components/bossanova-ui/js/jquery.jexcel.js"></script>

<div id="my"></div>