Angular6 模式表单动态选择

标签 angular angular-material jsonschema

我正在使用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 编写的库有所下降,但我需要一个适用于 Angular 和 Material 的解决方案。

非常感谢任何建议!

最佳答案

我过去在使用angular-schema-form-dynamic-select时遇到了问题,并放弃了它,转而采用普通的解决方案,然后我不得不将其移植到angular6-json中-schema-form 当我们获得将项目从 AngularJS 迁移到 Angular 7 的许可时。虽然它确实需要相当多的苦力,但它允许您填充数据或在表单初始化中执行您想要的任何其他操作,仅具有普通模式表单。

在我的上下文中|异步 不是一个选项,因为由于我无法控制的原因,数据获取返回了 bluebird promise ,它与异步过滤器不兼容。如果您没有这个限制,我会先尝试看看@Mic 的建议是否有效。

我创建了一个助手来获取 Promise 的结果(在我的例子中是 HAL REST 列表端点)并将其转换为标题图。就我而言,我总是想要元素的名称,或者如果失败的话,它的描述,所以这就是我所采用的:

  // 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 表示所有 Promise 均已解决,因此可以呈现表单而无需强制重绘:

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

不像嵌入式扩展那么简洁,但也能完成工作。

关于Angular6 模式表单动态选择,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55148959/

相关文章:

Angular 2 - 显示一个元素并隐藏其他元素,

python - 从json模式动态创建mongoengine类

用于匹配不能包含某些字符或子字符串的字符串的正则表达式

使用 ng serve 时 Angular2 APP Init [i] 错误

javascript - 从服务获取数据后如何刷新数据表内联编辑器?

html - Angular:ngIf 无法识别枚举类型

javascript - AngularJS Material 侧边栏元素不一致

html - Mat Select 多个设置选定值

javascript - 安装 Angular Material, "Failed to instantiate module ngMaterial"即使我使用的是 angular 版本 1.3.0

Json 架构文件扩展名