Схема Angular6 Dynamic Select - PullRequest
       9

Схема Angular6 Dynamic Select

2 голосов
/ 13 марта 2019

Я использую Angular6 JSON Schema Form

Где HTML-элемент select описывается с помощью json, как показано ниже:

  {
"schema": {
  "type": "object",
  "title": "My Form",
  "properties": {
    "select1552420741389": {
      "type": "string"
    }
  },
  "required": [
    "select1552420741389"
  ]
},
"layout": [
  {
    "key": "select1552420741389",
    "type": "select",
    "multiple": false,
    "notitle": false,
    "title": "Select",
    "titleMap": [
      {
        "name": "Option 1",
        "value": "option1"
      },
      {
        "name": "Option 2",
        "value": "option2"
      }
    ]
  }
],
"data": {}
}

И я хотел бы получитьвозможность динамически загружать titleMap с помощью пользовательской функции обратного вызова или указывать URL-адрес для вызова для получения данных titleMap.

Я видел падение библиотек, написанных на angular.js, но мне нужно решение, которое работает дляУгловой и материал.

Любые предложения очень ценятся!

Ответы [ 2 ]

2 голосов
/ 14 марта 2019

В прошлом у меня были проблемы с angular-schema-form-dynamic-select, и я отказался от него в пользу ванильного решения, которое мне пришлось портировать на angular6-json-schema-form, когда мы получили зеленый свет для переноса проекта с AngularJS на Angular 7. Хотя для этого требуется немалое количество консистентной смазки, оно позволяет вам заполнять данные или делать что-либо еще при инициализации формы только с формами ванильной схемы.

В моем контексте | async не было вариантом, потому что по независящим от меня причинам при извлечении данных возвращалось обещание Bluebird, которое несовместимо с асинхронным фильтром. Если у вас нет этого ограничения, я постараюсь проверить, работает ли сначала предложение @Mic.

Я создал помощника для получения результата обещания (в моем случае, конечной точки списка HAL REST) ​​и преобразования его в карту заголовка. В моем случае я всегда хочу, чтобы элемент name или, в противном случае, его description, вот с чем я столкнулся:

  // returns a [{name: name, value: link}, ...] mapping of items for form
  // display based on a promise whose result is a list of entities
  private formify(promise) {
    return promise
        .then(result => result._embedded[Object.keys(result._embedded)[0]].map(element => ({
          name: element.name || element.description,
          value: element._links.self.href
        })))
        .catch(error => console.log(error));
  }

Затем еще один помощник, который создает обратный вызов onInit:

  // returns an onInit callback for a simple select that is populated with
  // the list of entities supplied by the given promise
  private getStandardPromiseOnInit(formItem, promise) {
    return () => this.formify(promise)
        .then(function(result) {
          formItem.titleMap = result;
        })
        .catch(error => console.log(error));
  }

Затем я добавляю в элемент формы поле onInit:

  formItem.onInit = this.getStandardPromiseOnInit(formItem, callToRestService());

И после этой обработки мой объект определения формы (он использует синтаксис AngularJS, поскольку это был порт) будет выглядеть примерно так:

[
  {
    "key": "type",
    "placeholder": "...",
    "type": "select",
    "onInit": <function....>
  },
  {
    "key": "equipment",
    "placeholder": "...",
    "type": "select",
    "onInit": <other function....>
  },
  ...
]

У меня есть служба для получения определений форм, которая выполняет эту работу.

Затем при инициализации компонента формы я рекурсивно просматриваю объявление формы, отыскиваю обратные вызовы onInit и выполняю их:

  form: any;
  ready: boolean;

  ngOnInit() {
    ...
    this.populateForm();
  }

  populateForm: Function = () => {
    let onInits = [];
    if (this.form) {
      // recursively traverse the form json
      let traverse = item => {
        if (item.items) {
          item.items.map(traverse);
        } else if (item.tabs) {
          item.tabs.map(traverse);
        }

        // call onInit callbacks
        if (item.onInit) {
          onInits.push(item.onInit());
        }
      };
      this.form.map(traverse);
    }

    Promise.all(onInits)
        .then(() => this.ready = true)
        .catch(error => {
          // error handling and message display
        });
  };

this.ready сигнализирует о том, что все обещания были выполнены, поэтому форму можно отобразить без необходимости перерисовки:

<json-schema-form *ngIf="ready"
    ...
    [form]="form" 
    ...
>
</json-schema-form>

Не такой аккуратный, как вставное расширение, но делает свою работу.

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

Я сам не пробовал, но из readme видно, что привязка к атрибуту [layout]="yourJsonFormLayout" с обновлением yourJsonFormLayout по мере необходимости будет работать.

Вы также можетеиспользуйте канал | async для загрузки данных с URL-адреса, который вы запрашиваете, с учетом формата как в

this.yourJsonFormLayout = http.get(...).pipe(map(...format your object...));
...