Aurelia自定义元素访问从子视图模型到父视图模型的数据

时间:2018-04-12 16:53:33

标签: aurelia aurelia-binding aurelia-framework

我是Aurelia的新手,需要帮助在另一个视图中访问自定义元素的值。

我有一个场景,我希望以多种形式共享附件的输入文件。我正在采取的一种方法是为输入文件创建自定义元素,可以与Web应用程序中的多个表单共享。

以下是我的代码:

名为FilePicker的自定义元素,将在多个表单之间共享。在我的Request页面中,我插入了名为:

的自定义元素

<file-picker router.bind="router" accept="image/*" multiple="true" ></file-picker>

我的要求是访问名为validFiles的属性,这是一个数组。我想在validFiles视图模型Request

中使用formData['attachment']到自定义对象的值

TS:

import { customElement, useView, bindable, bindingMode } from 'aurelia-framework';

@customElement('file-picker')
@useView('./file-picker.html')
export class FilePicker {

  @bindable accept = '';
  @bindable multiple = false;
  @bindable({ defaultBindingMode: bindingMode.twoWay }) files: FileList;

  validFiles = [];
  input: HTMLInputElement;


  // Validate function for on change event to input file.
  public filesChanged() {
    if (!this.files) {
      this.clearSelection();
    }
    if (this.files) {
      this.processFiles();
    }
  }

  // Trigger on button click
  public triggerInputClick() {
    this.input.click();
  }

  // Find value in array of object
  private findValinArrObj(arr, key, val) {
    return arr.map(function (v) { return v[key] }).indexOf(val);
  }

  // Process file for each new files uploaded via browser
  private processFiles() {
    if (this.files) {
      for (let i = 0; i < this.files.length; i++) {
        let findFile = this.findValinArrObj(this.validFiles, 'name', this.files.item(i).name);
        if (findFile === -1) {
          this.validFiles.push(this.files.item(i));
        }
      }
      this.clearSelection();
    }
  }

  // Remove file from  fileNames and validFiles array
  public removeByFileName(fileName) {
    if (this.validFiles) {
      for (let i = 0; i < this.validFiles.length; i++) {
        if (this.validFiles[i].name === fileName) {
          this.validFiles.splice(i, 1);
        }
      }
    }
  }

  // Clear input file in DOM
  private clearSelection() {
    this.input.type = '';
    this.input.type = 'file';
  }
}

HTML:

<template>
  <input type="file" accept.bind="accept" multiple.bind="multiple"
         files.bind="files" ref="input"
         style="visibility: hidden; width: 0; height: 0;">
  <button class="btn btn-primary" click.delegate="triggerInputClick()">
    <slot>Browse...</slot>
  </button>
  <ul class="list-group" if.bind="validFiles">
    <li class="list-group-item" repeat.for="file of validFiles" style="padding: 0; border:none;">
      ${file.name} <span class="glyphicon glyphicon-remove text-danger" style="cursor: pointer;" click.delegate="removeByFileName(file.name)"></span>
    </li>
  </ul>
</template>

父视图模型:

TS:

export class Request {
  pageTitle: string = "Request Page";
  title: string = '';
  description: string = '';
  businessValue: string = '';
  emails: string = '';
  formData: object = {};

  public postData() {
    this.formData['title'] = this.title;
    this.formData['description'] = this.description;
    this.formData['businessValue'] = this.businessValue;
    this.formData['emails'] = this.emails;
    this.formData['attachment'] = [];
    console.log(this.formData);
  }
}

HTML:

<template>
  <require from="./request.css"></require>
  <require from="../../resources/elements/file-picker"></require>
  <div class="panel panel-primary">
    <div class="panel-heading">${pageTitle}</div>
    <div class="panel-body">
      <form class="form-horizontal">
        <div class="form-group">
          <label for="title" class="col-sm-2 control-label">Title</label>
          <div class="col-sm-10">
            <input type="text" value.two-way="title" class="form-control" id="title" placeholder="Brief one-line summary of the request">
          </div>
        </div>
        <div class="form-group">
          <label for="description" class="col-sm-2 control-label">Description</label>
          <div class="col-sm-10">
            <input type="text" value.two-way="description" class="form-control" id="description" placeholder="Detailed description of the request">
          </div>
        </div>
        <div class="form-group">
          <label for="description" class="col-sm-2 control-label">Business Value</label>
          <div class="col-sm-10">
            <input type="text" value.two-way="businessValue" class="form-control" id="description" placeholder="Description of how this offers business value">
          </div>
        </div>
        <div class="form-group">
          <label for="emails" class="col-sm-2 control-label">Email</label>
          <div class="col-sm-10">
            <input type="text" value.two-way="emails" class="form-control" id="emails" placeholder="Provide email address">
          </div>
        </div>
        <div class="form-group">
          <label for="exampleInputFile" class="col-sm-2 control-label">Attachment(s)</label>
          <div class="col-sm-10">
            <file-picker router.bind="router" accept="image/*" multiple="true" ></file-picker>
          </div>
        </div>

        <div class="form-group">
          <div class="col-sm-12">
            <button type="submit" class="btn btn-default pull-right" click.trigger="postData()">Submit</button>
          </div>
        </div>
      </form>
    </div>
  </div>
</template>

非常感谢任何帮助。 :)

1 个答案:

答案 0 :(得分:2)

您可以在two-way视图上设置Request - 绑定,将子视图中的validFilesfile-picker)绑定到父视图中的变量( Request):

request.html:

<file-picker valid-files.two-way="validFiles"></file-picker>

request.ts:

public validFiles: File[];

文件picker.ts:

@bindable
public validFiles: File[];

这样,对子节点或父节点中的validFiles对象所做的任何更改都将更新两个视图模型中的对象。