1

私はJavascriptが初めてで、KnockoutでGridsterを使用しようとしています。アイテムのデータベースがあり、ノックアウト foreach を使用してアイテムを UL にバインドしています。UL は Gridster ライブラリでスタイル設定されています。ビューモデルの ObservableArray を介して UL に要素を追加しようとしない限り、すべてうまく機能します。

ここでの操作の範囲と順序を理解するのを手伝ってくれる人はいますか? Gridster ライブラリが新しいウィジェットにスタイルを適用していないように感じます。

このjsfiddle は、問題の動作デモを示しています。ウィジェットをダブルクリックすると、新しいウィジェットが作成されますが、グリッドには配置されません。代わりに、後ろにぶら下がっているだけです。

ここにHTMLがあります

   <div class="gridster">
        <ul data-bind="foreach: myData">
            <li data-bind="attr:{

              'data-row':datarow,
              'data-col':datacol,
              'data-sizex':datasizex,
              'data-sizey':datasizey

        },text:text, doubleClick: $parent.AddOne"></li>
        </ul>
    </div>

ジャバスクリプトはこちら

//This is some widget data to start the process
var gridData = [ {text:'Widget #1', datarow:1, datacol:1, datasizex:1, datasizey:1},
    {text:'Widget #2', datarow:2, datacol:1, datasizex:1, datasizey:1},
    {text:'Widget #3', datarow:1, datacol:2, datasizex:1, datasizey:1},
    {text:'Widget #4', datarow:2, datacol:2, datasizex:1, datasizey:1}];

// The viewmodel contains an observable array of widget data to be 
//    displayed on the gridster
var viewmodel = function () {

    var self = this;
    self.myData = ko.observableArray(gridData);
    //AddOne adds an element to the observable array 
    //   (called at runtime from doubleClick events)
    self.AddOne = function () {
        var self = this;
        myViewModel.myData.push({
            text: 'Widget Added After!',
            datarow: 1,
            datacol: 1,
            datasizex: 1,
            datasizey: 1
        });
    };

};


var myViewModel = new viewmodel();
ko.applyBindings(myViewModel);

$(".gridster ul").gridster({
    widget_margins: [5, 5],
    widget_base_dimensions: [140, 140]
});
4

4 に答える 4

2

JSfiddleの完全な例を次に示します。ここでは、削除機能のみを強調表示しています

self.deleteOne = function (item) {
    console.log(item);
    var widget = $("#" + item.id);
    console.log(widget);
    var column = widget.attr("data-col");
    if (column) {
        console.log('Removing ');
        // if this is commented out then the widgets won't re-arrange
        self.gridster.remove_widget(widget, function(){
            self.myData.remove(item);
            console.log('Tiles: '+self.myData().length);                
        });
    }
};

監視可能な配列から要素を削除する作業は、remove_widget コールバック内で行われます。gridster のドキュメントを参照してください。その結果、ウィジェットが削除される前に実行される removeGridster フックは、実際の remove_widget 呼び出しを行う必要がなくなりました。

于 2014-06-21T21:34:52.617 に答える
1

これは、MVVMパターンとより一致していると思われる実用的なソリューションです。

http://jsfiddle.net/Be4cf/4/

//This is some widget data to start the process
var gridData = [
    {id: "1", text:'Widget #1', datarow:1, datacol:1, datasizex:1, datasizey:1},
    {id: "2", text:'Widget #2', datarow:1, datacol:2, datasizex:2, datasizey:1},
    {id: "3", text:'Widget #3', datarow:1, datacol:4, datasizex:1, datasizey:1},
    {id: "4", text:'Widget #4', datarow:2, datacol:1, datasizex:1, datasizey:2}];

// The viewmodel contains an observable array of widget data to be 
//    displayed on the gridster
var viewmodel = function () {

    var self = this;
    self.myData = ko.observableArray(gridData);
    self.nextId = 5;
    self.gridster = undefined;

    // AddOne adds an element to the observable array.
    // Notice how I'm not adding the element to gridster by hand here. This means  
    // that whatever the source of the add is (click, callback, web sockets event), 
    // the element will be added to gridster.
    self.addOne = function () {
    myViewModel.myData.push({
            text: 'Widget Added After!',
            datarow: 1,
            datacol: 1,
            datasizex: 1,
            datasizey: 1,
            id: self.nextId++
        });
    };

    // Called after the render of the initial list.
    // Gridster will add the existing widgets to its internal model.
    self.initializeGridster = function() {
        self.gridster = $(".gridster ul").gridster({
            widget_margins: [5, 5],
            widget_base_dimensions: [140, 140]
        }).data('gridster');
    };

    // Called after the render of the new element.
    self.addGridster = function(data, object) {
        // This bypasses the add if gridster has not been initialized.
        if (self.gridster) {
            var $item = $(data[0].parentNode);

            // The first afterRender event is fired 2 times. It appears to be a bug in knockout.
            // I'm pretty new to knockout myself, so it might be a feature too! :)
            // This skips the second call from the initial fired event.
            if (!$item.hasClass("gs-w"))
            {
                // This removes the binding from the new node, since gridster will re-add the element.
                ko.cleanNode(data[0].parentNode);
                // Adds the widget to gridster.
                self.gridster.add_widget($item);
                // We must update the model with the position determined by gridster
                object.datarow = parseInt($item.attr("data-row"));
                object.datacol = parseInt($item.attr("data-col"));
            }
        }
    };
};

var myViewModel = new viewmodel();
ko.applyBindings(myViewModel);

remove イベントと move イベントについてまだ考える必要があります (gridster での移動は、viewmodel 内のアイテムの x 値と y 値を更新する必要があります)。昨日ノックアウトを使い始めたので、助けていただければ幸いです。

gridster の最新バージョンの CDN が見つかりませんでした。JSFiddle は、私が Azure に追加した一時的な Web サイトを指しています。数日間そのままにしておきますが、独自のリンクで自由に更新してください。

/ - - - - - - - - - - - - - - - アップデート - - - - - - - - - ----------------/

削除とウィジェットの移動をサポートするようにコードを更新しました ( http://jsfiddle.net/Be4cf/11/ ) が、小さな注意点があります: 未解決の問題があります ( https://github.com/knockout/knockout/issues /1130 ) ノックアウトは beforeRemove イベントを呼び出す前に jquery データを消去します。これにより、他のアイテムを移動するために必要なデータがデータ要素に保持されるため、gridster がクラッシュします。回避策として、データのコピーを保持し、後で要素に再度追加することもできますが、私は怠惰な方法を選択し、問題のある行をノックアウトでコメントしました。

于 2013-11-19T19:49:05.680 に答える
0

以下のようにする必要があります。Knockout オブザーバブルに何かを追加すると、最初の引数として DOM 要素を受け入れるためaddNewGridElement、Gridster の場合に重要なレンダリングされた DOM 要素を使用して呼び出されます。gridster.add_widgetあとはdomNodeGridsterに追加するだけです。

view.html:

   <div class="gridster">
        <ul data-bind="foreach: { myData, afterAdd: $root.addNewGridElement }">
            <li data-bind="attr:{

              'data-row':datarow,
              'data-col':datacol,
              'data-sizex':datasizex,
              'data-sizey':datasizey

        },text:text, doubleClick: $parent.AddOne"></li>
        </ul>
    </div>

ビュー.js:

self.addNewGridElement = function (domNode, index, newTile) {
    // Filter non li items - this will remove comments etc. dom  nodes.
    var liItem = $(domNode).filter('li');
    if ( liItem.length > 0 ) {
        // Add new Widget to Gridster
        self.gridster.add_widget(domNode, newTile.x, newTile.y, newTile.row, newTile.col);
    }
};
于 2014-07-09T15:48:22.247 に答える