2

私はばかげた問題を抱えています。私の唯一の解決策は、他の問題を引き起こしているずさんなハックです。

私のフィドルを見て、

またはここでコードを読んでください:

HTML:

<input id='1' value='input1' />
<template id='template1'>
    <input id='2' value='input2' />
</template>

JS - アイテム ビュー宣言:

// Declare an ItemView, a simple input template.
var Input2 = Marionette.ItemView.extend({

    template: '#template1',
    onRender: function () {
        console.log('hi');
    },

    ui: { input2: '#2' },

    onRender: function () {

        var self = this;

        // Despite not being in the DOM yet, you can reference
        // the input, through the 'this' command, as the
        // input is a logical child of the ItemView.
        this.ui.input2.val('this works');

        // However, you can not call focus(), as it 
        // must be part of the DOM.
        this.ui.input2.focus();

        // So, I have had to resort to this hack, which 
        // TOTALLY SUCKS.

        setTimeout(function(){
          self.ui.input2.focus();
          self.ui.input2.val('Now it focused. Dammit');  
        }, 1000)
    },

})

JS-コントローラー

// To start, we focus input 1. This works.
$('#1').focus();

// Now, we make input 2.
var input2 = new Input2();

// Now we 1. render, (2. onRender is called), 3. append it to the DOM.
$(document.body).append(input2.render().el);

上記でわかるように、私の問題は、ビューがonRenderまだDOMに追加されていないため、ビューがレンダリングされた後()、それ自体にフォーカスを当てることができないことです。私の知る限り、 などと呼ばれる他のイベントはありませんonAppend。これにより、実際に DOM に追加されたことを検出できます。

ItemView の外からフォーカスを呼び出したくありません。それは私の目的のために内部から行われなければなりません。

明るいアイデアはありますか?

アップデート

onShow()CollectionView、CompositeView、Region など、Marionette.js のすべての DOM 追加で呼び出されますが、ドキュメントにはありません。

ありがとう、ルカシュフィッツァー。

4

2 に答える 2

3

ItemView解決策は、あなたの内部をレンダリングすることMarionette.Regionです. このようにして、onShowメソッドが DOM に挿入されると、そのビューでメソッドが呼び出されます。

例:

HTML

<input id='1' value='input1' />
<div id="inputRegion"></div>
<template id='template1'>
  <input id='2' value='input2' />
</template>

JSアイテムビュー

(...)

onShow: function () {
    this.ui.input2.val('this works');
    this.ui.input2.focus();
},

(...)

JS コントローラー

$('#1').focus();

var inputRegion = new Backbone.Marionette.Region({
  el: "#inputRegion"
});

var input2 = new Input2();

inputRegion.show(input2);

マリオネットのドキュメントの詳細: https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.region.md#region-events-and-callbacks

于 2013-10-09T01:12:55.570 に答える
1

まあ、Marionette.js を拡張することでなんとか解決できましたが、ライブラリの拡張を伴わないより良いアイデアを誰かが持っている場合は、喜んでそれを受け入れてドーナツを購入します。

// After studying Marionette.js' annotated source code,
// I found these three functions are the only places
// where a view is appended after rendering. Extending
// these by adding an onAppend call to the end of
// each lets me focus and do other DOM manipulation in
// the ItemView or Region, once I am certain it is in
// the DOM.

_.extend(Marionette.CollectionView.prototype, {
  appendHtml: function(collectionView, itemView, index){
    collectionView.$el.append(itemView.el);
    if (itemView.onAppend) { itemView.onAppend() }
  },
});

_.extend(Marionette.CompositeView.prototype, {
  appendHtml: function(cv, iv, index){
    var $container = this.getItemViewContainer(cv);
    $container.append(iv.el);
    if (itemView.onAppend) { itemView.onAppend() }
  },  
});

_.extend(Marionette.Region.prototype, {
 open: function(view){
    this.$el.empty().append(view.el);
    if (view.onAppend) { view.onAppend() }
  },  
});
于 2013-10-09T01:12:14.390 に答える