【问题标题】:Ember Observe DOM EventEmber 观察 DOM 事件
【发布时间】:2014-08-20 23:27:09
【问题描述】:

我正在尝试在 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

所以我要解决的真正问题是如何从可在姐妹元素 fileUpload 中听到/执行的 resetButton 启动动作/功能/事件。当我点击执行我的重置按钮时,我清除了输入元素,我想我需要一些如何从我的 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>'

提前致谢!

【问题讨论】:

标签: javascript jquery html dom ember.js


【解决方案1】:

您可以在您的视图中显示:&lt;button {{action reset}}&gt;Reset&lt;/button&gt;,然后让该操作处理您想要做的事情。

【讨论】:

  • 提供更多信息会更好。举个例子会很有帮助。
  • 我有一个手风琴组件,里面有一个“photoUpload”组件。在“photoUpload”内部有一个“fileUpload”组件和两个按钮。所以我正在使用一个动作来捕捉按钮按下然后对服务进行ajax调用,但是当我处于“photoUpload”级别时,我看不到如何修改“fileUpload”组件中的某些内容。我会更新我的帖子。
【解决方案2】:

我最终需要使用一个简单的绑定。我误解了绑定在 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-15
    • 2015-10-18
    相关资源
    最近更新 更多