Ember观察DOM事件

时间:2014-08-20 23:27:10

标签: javascript jquery html dom ember.js

我正在尝试在ember中构建表单元素。表单元素包含用于上传图片的Ember视图/组件,一旦上传图片,则显示图片的缩略图。表单还包含重置和提交按钮。单击“重置”时,文件输入框将清除,因此我知道“onreset”DOM事件正在触发。让我尝试图:

Accordion: {
    photoUpload: {
          fileUpload: {
              input: {}
          },
          resetButton,
          saveButton
    }
}

Accordion: simply houses components and handles its own open/close actions.  
photoUpload: has both a template and a view/controller.  
    photoUpload.hbs: has a form element that houses the fileUpload component and the two buttons.  
    photoUpload.js: handles the actions from the template, such as making the call to the web services.
fileUpload: Handles the uploading of files, determining there type and displaying a preview/thumbnail if the file is an image.
input: handles file browsing

所以我试图解决的真正问题是如何从resetButton中启动一个可以在姐妹元素fileUpload中听到/执行的动作/功能/事件。当我点击执行我的重置按钮时,我清除输入元素我认为我需要一些如何从我的fileUpload组件中观察此输入组件中的属性,然后清除图像预览。

以下是photoUpload模板的示例:

<p>Upload a photo.</p>
<form {{action 'savePhoto' on='submit'}}>
    {{view FileUpload showPreview=true showProgress=true valueBinding="photo" fileBinding="view.file"}}
    <div class="controls">
        {{#view Button type="secondary" function="reset" action="resetPhoto"}}Cancel{{/view}}
        <input class="primary" type="submit" value="Save">
    </div>
</form>

以下是输入组件的示例:

function() {
    var _InputElement = Ember.View.extend({
        tagName:           'input',
        attributeBindings: ['type', 'name', 'value', 'readonly', 'disabled', 'required'],

        typeBinding:     'parentView.type',
        idBinding:       'parentView.GUID',
        valueBinding:    'parentView.value',
        readonlyBinding: 'parentView.readonly',
        disabledBinding: 'parentView.disabled',
        requiredBinding: 'parentView.required',
        nameBinding:     'parentView.name',

        change: Ember.aliasMethod( '_updateValue' ),
        keyUp:  Ember.aliasMethod( '_updateValue' ),

        _updateValue: function() {
            var old     = this.get( 'value' );
            var current = this.$().val();

            if( current != old ) { // -- value actually changed
                this.set( 'value', this.$().val());
            }
        }
    });

    return Ember.View.extend({
        classNames:        ['input'],
        classNameBindings: ['error:error', '_typeClass'],
        attributeBindings: ['data-label', 'data-name', 'readonly', 'disabled', 'required'],
        _InputElement:     _InputElement,

        type:                 'text', // text, password, radio, checkbox, select, etc
        error:                null,
        label:                null,
        prefix:               null,
        postfix:              null,
        name:                 null,
        value:                null,
        readonly:             false,
        disabled:             false,
        showInputBeforeLabel: false,

        'data-name': function() {
            var name = this.get( 'name' );
            return (!Ember.isEmpty( name ) ? name.camelize() : undefined);
        }.property( 'name' ),

        'data-label': function() {
            var label = this.get( 'label' );
            return (!Ember.isEmpty( label ) ? label.camelize() : undefined);
        }.property( 'label' ),

        _typeClass: function() {
            return 'input-%@'.fmt( this.get( 'type' ));
        }.property( 'type' ),

        _InputElementGUID: function() {
            var childViews = this.get('childViews');

            if ( childViews && childViews[0] ) { // -- only works if there is ONE child view, as in, ONE _InputElement
                return childViews[0].get('elementId');
            }
        }.property( '_InputElement', 'childViews.[]' ),

        _yieldTemplate: '{{yield}}',

        _labelTemplate:     '<label {{bind-attr for="view._InputElementGUID"}}>{{view.label}}</label>',
        _preLabelTemplate:  function() { return '{{#if view.label}}{{#unless view.showInputBeforeLabel}}' + this.get( '_labelTemplate' ) + '{{/unless}}{{/if}}'; }.property(),
        _postLabelTemplate: function() { return '{{#if view.label}}{{#if     view.showInputBeforeLabel}}' + this.get( '_labelTemplate' ) + '{{/if}}{{/if}}'; }.property(),

        _errorTemplate: '{{#if view.error}}<label class="error form-error" {{bind-attr for="view._InputElementGUID"}}>{{view.error}}</label>{{/if}}',

        _prefixTemplate:  '{{#if view.prefix }}<div class="prefix  input-prefix" >{{view.prefix }}</div>{{/if}}',
        _postfixTemplate: '{{#if view.postfix}}<div class="postfix input-postfix">{{view.postfix}}</div>{{/if}}',

        layout: function() {
            return Ember.Handlebars.compile( ''
                + this.get('_preLabelTemplate') + '\n'
                + this.get('_prefixTemplate') + '\n'
                + this.get('_yieldTemplate') + '\n'
                + this.get('_postfixTemplate') + '\n'
                + this.get('_postLabelTemplate') + '\n'
                + this.get('_errorTemplate')
            )
        }.property(),

        template: Ember.Handlebars.compile( '{{view view._InputElement}}' )
    });
});

并且输入组件的使用方式如下:

'<div class="input-file-button-wrapper">{{view view._InputElement}}</div>\
    <div class="input-file-preview-wrapper">\
        <img {{bindAttr src="view.file"}} {{bindAttr title="view.fileName"}}/>\
    </div>'

提前致谢!

2 个答案:

答案 0 :(得分:1)

您可以在视图中使用此功能:<button {{action reset}}>Reset</button>并让该操作处理您想要执行的操作。

答案 1 :(得分:0)

我最终需要使用简单的绑定。我误解了绑定在Ember中是如何工作的,并且认为绑定变量/属性只能在与该视图/组件实例化相关联的操作中使用。实际上,您可以使用实例化其他组件的组件内部的任何绑定变量。我的解决方案是绑定我在fileUpload组件中找到的变量“haveUploadedFile”。然后在使用我的重置按钮启动的操作中,我将该变量设置为false。

希望这可以帮助有人在路上。

fileUpload.hbs现在看起来像这样:

<p>Upload a headshot.</p>
<form {{action 'savePhoto' on='submit'}}>
    {{view Vember.FileUpload showPreview=true showProgress=true valueBinding="photo" fileBinding="view.file" haveUploadedFileBinding="view.haveUploadedFile"}}
    <div class="controls">
        {{#view Vember.Button type="secondary" function="reset" action="resetPhoto"}}Cancel{{/view}}
        <input class="primary" type="submit" value="Save">
    </div>
</form>