Alpaca JS: наблюдаемые поля ссылок в строке таблицы Dynami c - PullRequest
0 голосов
/ 06 мая 2020

У меня есть элемент таблицы, где люди могут добавлять строки для добавления данных. Два поля являются взаимоисключающими: если вы вводите значение в одно, другое должно быть отключено, и наоборот. Насколько я понимаю, мне нужно сделать это в обратном вызове postRender с использованием наблюдаемых, но я не могу найти правильный путь или строку идентификаторов. И логически не имеет большого смысла, как это будет работать. Таблица начинается пустой.

Так есть ли обратный вызов для кнопки «Добавить строку» или что-то еще, где мне нужно добавить этот logi c? Любые указания будут оценены.

Схема:

    var schema = {
        "type": "object",
        "properties": {
            "cbnum": {
                "type": "string",
                "required": true,
                "minLength": 5,
                "maxLength": 5
            },
            "projects": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "name": {
                            "type": "string",
                            "title": "Project name (required)",
                            "required": true
                        },
                        "tags": {
                            "type": "string",
                            "title": "Tags"
                        },
                        "hours": {
                            "type": "number",
                            "title": "Hours"
                        },
                        "percent": {
                            "type": "number",
                            "title": "Percent"
                        }
                    }
                }
            }
        }
    };

Следующий код не работает (опять же, неудивительно, когда вы думаете об этом, но я не знаю, что еще попробовать ):

    var postRenderCallback = function(control) {
        var hours = control.childrenByPropertyId["projects"].childrenByPropertyId["hours"];
        var percent = control.childrenByPropertyId["projects"].childrenByPropertyId["percent"];
        hours.on("change", function() {
            if (this.getValue().length > 0) {
                percent.setValue("");
                percent.options.disabled = true;
            } else {
                percent.options.disabled = false;
            }
        });
        percent.on("change", function() {
            if (this.getValue().length > 0) {
                hours.setValue("");
                hours.options.disabled = true;
            } else {
                hours.options.disabled = false;
            }
        });
    };

Обновление

Следующее postRenderCallback исправило постоянную проблему с отключением:

    var postRenderCallback = function(control) {
        var table = control.childrenByPropertyId["projects"];
        table.on("add", function() {
            var lastrow = this.children[this.children.length-1];
            var hours = lastrow.childrenByPropertyId["hours"];
            var percent = lastrow.childrenByPropertyId["percent"];
            hours.options.disabled = false;
            percent.options.disabled = false;
            hours.refresh();
            percent.refresh();
        });
    };

Но затем я столкнулся с парой других проблем, которые только что сделали вся эта проблема решения c (большая проблема заключается в том, что я не могу найти способ просто установить числовое поле пустым или undefined; он продолжает отображаться как NaN). Поэтому я выбрал следующее решение, которого достаточно. Вот соответствующий фрагмент объекта options:

            "projects": {
                "type": "table",
                "actionbarStyle": "bottom",
                "items": {
                    "fields": {
                        "tags": {
                            "type": "tag"
                        },
                        "hours": {
                            "allowOptionalEmpty": true,
                            "validator": function (callback) {
                                var that = this.parent.childrenByPropertyId["percent"];
                                var thisValue = this.getValue();
                                var thatValue = that.getValue();
                                if ( (typeof thisValue !== "undefined" && !isNaN(thisValue)) && (typeof thatValue !== "undefined" && !isNaN(thatValue)) ) {
                                    callback({
                                        "status": false,
                                        "message": "You can only enter a number into one of the fields, if any. You may not have numbers in both."
                                    });
                                } else {
                                    callback({
                                        "status": true
                                    });
                                }
                            }
                        },
                        "percent": {
                            "allowOptionalEmpty": true,
                            "validator": function (callback) {
                                var that = this.parent.childrenByPropertyId["hours"];
                                var thisValue = this.getValue();
                                var thatValue = that.getValue();
                                if ( (typeof thisValue !== "undefined" && !isNaN(thisValue)) && (typeof thatValue !== "undefined" && !isNaN(thatValue)) ) {
                                    callback({
                                        "status": false,
                                        "message": "You can only enter a number into one of the fields, if any. You may not have numbers in both."
                                    });
                                } else {
                                    callback({
                                        "status": true
                                    });
                                }
                            }
                        }
                    }
                }
            }

Все еще не идеальное решение UX (я не могу заставить валидатор одного поля выполнять валидатор другого поля; я пробовал this.parent.validate(true)), но на данный момент он достаточно функционален.

1 Ответ

1 голос
/ 07 мая 2020

Ваша схема верна, и то, о чем вы думали, тоже правильно, использование postRender всегда помогает, но в этом случае не слишком сильно, потому что у вас есть вложенные поля / объекты (массив> элементы> элемент 1> часы) это вот почему ваш код не работал, потому что вы не можете назначить функцию изменения для всех часов всех созданных элементов! плюс вы используете getValue().length для числа (см. конфигурацию вашей схемы), и это никогда не сработает, вы должны либо использовать toString, либо isNaN в number полях.

Итак, чтобы достичь того, что вы ищете, вы должны создать options config и назначить его в поле параметров альпаки. И в этой конфигурации вы должны использовать поля change event в процентах и ​​часах и ввести тот же код, который вы уже использовали в postRender для каждого из них.

Вот пример:

"hours": {
   "events": {
       "change": function() {
            var percent = this.parent.childrenByPropertyId["percent"];
            var hoursValue = this.getValue();
            if (typeof hoursValue != 'undefined' && !isNaN(hoursValue)) {
              percent.options.disabled = true;
            } else {
              percent.options.disabled = false;
            }
            percent.refresh();
        }
    }
}

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

var percent = this.parent.childrenByPropertyId["percent"];

После того, как вы установили какие-либо параметры в поле часов или процентов, вы должны вызвать функцию refresh(), чтобы сообщить alpaca, что вы обновили некоторую конфигурацию, и повторно отобразить поле для нас, используя эту обновленную конфигурацию.

percent.refresh();

Вот рабочая скрипка для этого решения.

И, чтобы ответить на ваш вопрос о кнопке «Добавить строку», да, для этого есть обратный вызов, но я не думаю, это поможет вам, хотя я пробовал, с полем типа массива у вас есть 2 разные кнопки добавления, поэтому для меня это не очень хорошее решение, потому что вы должны реализовать код для обеих кнопок! первый, когда у вас есть 0 элементов (кнопка панели инструментов), и второй, когда вы начинаете добавлять элементы (кнопка действия).

...