1

基本的な Ember アプリケーションがあります。選択要素とテキスト フィールドの 2 つのコントロールがあります。コントロールは、表示されるデータを変更するために使用されます。select 要素を使用すると、すべての数字、偶数のみ、または奇数のみを表示するように選択できます。テキスト フィールドを使用して、入力した数字を含む数字を検索できます。

コントロールが独立して動作する必要があることを望みます。つまり、select 要素からオプションを選択した後にテキスト フィールドに入力すると、select 要素がリセットされます。同様に、select 要素からオプションを選択すると、テキスト フィールドがクリアされます。

this.set('query', '')のオブザーバーを呼び出すと、のときにすべての数値を設定するようにプログラムされている のオブザーバーselectがトリガーされるため、これを実装するのは難しいと思います。つまり、このアプローチでは、偶数を選択するとテキスト フィールドがクリアされ、すべての数字が表示されてしまいます。これは、偶数が選択されたため間違っています。querycontentquery === ''

メソッドの値をチェックすることで、うまく機能するようになりましselectquery_changed。これは悪い解決策のように感じます。2 つ以上のコントロールが存在する場合、このアプローチではオブザーバーが多くの if ステートメントでいっぱいになると思います。

query_changed: function() {
    var query = this.get('query');
    if (query === '') {
        if (this.get('select').value === '') {  // <-- is there a better way?
            this.set('content', this.get('numbers'));
        }
    } else {
        var output = $.map(this.get('numbers'), function(number, i) {
            if (_.string.include(number, query)) {
                return number;
            }
            return null;
        });
        this.set('content', output);
    }
}.observes('query')

他のアイデアもいくつか試しましたが、基本的には上記のようなものでした。

Emberでこれをどのように処理することになっていますか? 私が見たところEmber.StateManager、複数のビューを処理するためのもののようです。ここでは、ステートフル コントロールを持つビューが 1 つだけあります。

デモ: http://jsfiddle.net/DxbeB/1/

コントロールを同期するための何もないコード:

App = Ember.Application.create({});
App.controller = Ember.Object.create({
    numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],
    contentBinding: Ember.Binding.oneWay('numbers'),
    select: null,
    query: null,
    select_changed: function() {
        if (this.get('select').value === 'all') {
            this.set('content', this.get('numbers'));
        }
        if (this.get('select').value === 'even') {
            var output = $.map(this.get('numbers'), function(number, i) {
                if (number % 2 === 0) {
                    return number;
                }
                return null;
            });
            this.set('content', output);
        }
        if (this.get('select').value === 'odd') {
            var output = $.map(this.get('numbers'), function(number, i) {
                if (number % 2 !== 0) {
                    return number;
                }
                return null;
            });
            this.set('content', output);
        }

    }.observes('select'),
    query_changed: function() {
        var query = this.get('query');
        if (query === '') {
            this.set('content', this.get('numbers'));
        } else {
            var output = $.map(this.get('numbers'), function(number, i) {
                if (_.string.include(number, query)) {
                    return number;
                }
                return null;
            });
            this.set('content', output);
        }
    }.observes('query')
});

App.Select = Ember.Select.extend({
    content: [{label: '', value: ''}, {label: 'All numbers', value: 'all'}, {label: 'Even numbers', value: 'even'}, {label: 'Odd numbers', value: 'odd'}],
    optionLabelPath: 'content.label',
    optionValuePath: 'content.value'
});

App.MyView = Ember.View.extend({
    controllerBinding: 'App.controller'
});

テンプレート:

{{#view App.MyView}}
    {{view App.Select selectionBinding="controller.select"}}
    {{view Ember.TextField valueBinding="controller.query"}}
    <p>{{controller.content}}</p>
{{/view}}
4

1 に答える 1

3

コントローラーに値が設定されていることを確認してからodd/even filter値をリセットする queryことも、その逆も可能です。http://jsfiddle.net/pangratz666/bWT4E/を参照してください。

ハンドルバー:

<script type="text/x-handlebars" >
    {{#view App.MyView}}
        {{view App.Select selectionBinding="select"}}
        {{view Ember.TextField valueBinding="query"}}
        <hr/>
        {{#each controller.filtered}}
            {{this}}
        {{/each}}   
    {{/view}}
</script>​

JavaScript :

App = Ember.Application.create({
    oddFilter: function(value) {
        return value % 2 === 1;
    },
    evenFilter: function(value) {
        return value % 2 === 0;
    },
    queryFilter: function(query) {
        return function(value) {
            return (value + '').indexOf(query) !== -1;
        };
    }
});

App.Select = Ember.Select.extend({
    prompt: 'define filter',
    content: ['odd', 'even']
});

App.controller = Ember.ArrayProxy.create({
    content: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30],

    _queryChanged: function() {
        var q = this.get('query');
        if (!Ember.empty(q)) {
            this.set('select', null);
        }
    }.observes('query'),

    _selectChanged: function() {
        var s = this.get('select');
        if (!Ember.none(s)) {
            this.set('query', null);
        }
    }.observes('select'),

    filtered: function() {
        var s = this.get('select');
        var q = this.get('query');
        var filter = Ember.K;
        if (s === 'odd') {
            filter = App.get('oddFilter');
        } else if (s === 'even') {
            filter = App.get('evenFilter');
        } else if (!Ember.empty(q)) {
            filter = App.get('queryFilter')(q);
        }

        return this.filter(filter, this);
    }.property('select', 'query').cacheable()
});

App.MyView = Ember.View.extend({
    controllerBinding: 'App.controller',
    selectBinding: 'controller.select',
    queryBinding: 'controller.query'
});​

あなたの質問に関して:常にとif (this.get('select').value === '') { // <-- is there a better way?を介してプロパティにアクセスしてください。これにより、Ember のバインディングが期待どおりに機能することが保証されます。また、いくつかのユーティリティ関数があるため、空文字列のチェックは 経由で実行できます。それについてのブログ投稿を参照してください: http://code418.com/blog/2012/03/08/useful-emberjs-functions/setgetEmber.empty(value)

于 2012-05-04T06:44:18.637 に答える