Ember链接到车把和jQuery DataTables

时间:2014-01-10 16:52:40

标签: jquery ember.js datatables handlebars.js

我有一个Ember View,它在给定一组列和一个数据源时设置jQuery Datatables。在我的例子中,这个数据源来自Ember Data。

我将它用于管理面板,因此我将列出模型中的一些行,然后我将允许管理员对这些项执行操作。操作可以包括“编辑”链接或“删除”链接等。

现在,我使用Datatable的mRender功能创建指向相应页面的链接。这工作得很好,但强制浏览器刷新有点烦人。我想改用Ember的link-to功能。

我试过这样的事情:

Ember.Handlebars.compile('{{#link-to "modelName", ' + full.id + '}}Edit{{/link-to}}');

但是,compile将返回一个javascript函数而不是直接的html文本。任何人都可以给我一些建议或代码片段来帮助实现这个功能吗?

这是一个模仿我当前架构的JSBin:JSBin Example

更新

我在路由器中使用location: 'history'而不是传统的哈希网址。

1 个答案:

答案 0 :(得分:4)

{{link-to}}帮助器可以在模板中使用,但由于您通过mRender指定了HTML,因此可以在构建的href和适当的路径中添加主题标签。在这种情况下,将不会刷新页面。

http://emberjs.jsbin.com/uYeXixiw/1/edit

<强> JS

App.Router.map(function() {
  this.route('details',{path:'user/:user_id'});
});

var data = [
      { 'id': 1, 'firstName': 'Tom', 'lastName': 'Dale' },
      { 'id': 2, 'firstName': 'Yehuda', 'lastName': 'Katz' },
      { 'id': 3, 'firstName': 'Peter', 'lastName': 'Wagenet' }
    ];

App.DetailsRoute = Ember.Route.extend({

model:function(params){
return data[params.user_id-1];
}
});



App.IndexRoute = Ember.Route.extend({
  setupController: function(controller, model) {
    controller.set('model', model);
    var columns = [
      { "sClass": "item", "mData": "firstName" },
      { "sClass": "item", "mData": "lastName" },
      { "sClass": "item", "mData": null, "bSearchable": false, "bSortable": false, "mRender": function ( data, type, full ) {
          return '<a href="#/user/' + full.id + '/">View Details</a>';
        }
      }
    ];
    controller.set('columns', columns);
  },
  model: function() {
    return data;
  }
});

App.DataTableView = Em.View.extend({
  tagName:'table',
  columnsBinding: 'controller.columns',
  didInsertElement: function() {
    var self = this;
    var value = this.get('value');
    var data = null;
    if(value === null || value === undefined) {
      console.log('Value is null');
      data = [];
    } else {
      console.log('Got Value: ' + JSON.stringify(value));
      data = value;//value.getEach('data'); //for Ember Data
      var items = JSON.stringify(data);
    }

    var columns = this.get('columns');
    this.$().dataTable( {
      "bJQueryUI": true,
      "aaData": data,
      "aoColumns": columns,
      "sEmptyTable": "Loading data from server"
    });
  },
  onValueChanged: function() {
    var self = this;
    var value = this.get('value');
    var data = null;
    if(value === null || value === undefined) {
      console.log('Value is null');
      data = [];
    } else {
      console.log('Got Value: ' + JSON.stringify(value));
      data = value;//value.getEach('data'); //for Ember Data
    }
    var columns = this.get('columns');
    this.$().dataTable( {
      "bJQueryUI": true,
      "aaData": data,
      "aoColumns": columns,
      "sEmptyTable": "Loading data from server"
    });
    return;
  }.observes('value')
});

<强> HBS

<script type="text/x-handlebars">
    <h2> Welcome to Ember.js</h2>

    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="index">
    {{view App.DataTableView valueBinding="model" columnsBinding="columns"}}
  </script>

<script type="text/x-handlebars" data-template-name="details">
    <h2>details</h2>

    {{controller.firstName}}
<br/>
{{#link-to 'index'}}back{{/link-to}}
  </script>

编辑 - 对评论的回复 - 对历史记录位置的支持

我注意到有时需要使用纯js从DOM访问ember个实体。如果与UI相关的另一个js框架难以被templating ember系统采用,则会发生这种情况。真正有趣的是能够以简单的方式实现这一点,而不会破坏您的系统的良好设计和关注的分离。

因此,在您的情况下,因为无法使用handlebars助手,例如{{link-to}}{{action}},对于已经呈现的模板,可以从DOM事件中调用ember实体。

返回传递DOM元素的视图的泛型函数

function getView($el){
  return Ember.View.views[$el.closest(".ember-view").attr("id")];
}

mRender中用作

 ....
return '<a href=# onclick="getView($(this)).get(\'controller\').send(\'showDetails\',' + full.id + ')">View Details</a>';

http://emberjs.jsbin.com/UnUdUpO/1

(由于jsbin,路径设置有点奇怪,但你明白了)

同样如jsbin中所述,如果使用<a>标记,那么转换工作需要preventDefault(即在视图的didInsertElement回调中)。

<强> JS

App = Ember.Application.create();

App.Router.reopen({
  location: 'history'
});

App.Router.map(function() {
  this.route('index', {path: '/UnUdUpO/1' }); //For jsbin
  this.route('details',{ path:'/UnUdUpO/1/user/:user_id' });
});

var data = [
  { 'id': 1, 'firstName': 'Tom', 'lastName': 'Dale' },
  { 'id': 2, 'firstName': 'Yehuda', 'lastName': 'Katz' },
  { 'id': 3, 'firstName': 'Peter', 'lastName': 'Wagenet' }
];

function getView($el){
  return Ember.View.views[$el.closest(".ember-view").attr("id")];
}


App.DetailsRoute = Ember.Route.extend({
  model:function(params){
    return data[params.user_id-1];
  }
});

App.IndexRoute = Ember.Route.extend({
  setupController: function(controller, model) {
    controller.set('model', model);
    var columns = [
      { "sClass": "item", "mData": "firstName" },
      { "sClass": "item", "mData": "lastName" },
      { "sClass": "item", "mData": null, "bSearchable": false, "bSortable": false, "mRender": function ( data, type, full ) {
        //if using an <a> tag element for ember transition, then preventDefault is required
          return '<a href=# onclick="getView($(this)).get(\'controller\').send(\'showDetails\',' + full.id + ')">View Details</a>';
        /*return '<button onclick="getView($(this)).get(\'controller\').send(\'showDetails\',' + full.id + ')" >details</button>';*/
        }
      }
    ];
    controller.set('columns', columns);
  },
  model: function() {
    return data;
  }
});

App.IndexController = Ember.ArrayController.extend({
  actions:{
    showDetails:function(userId){
      this.transitionToRoute('details',userId);
    }
  }
});

App.DataTableView = Em.View.extend({
  tagName:'table',
  columnsBinding: 'controller.columns',
  didInsertElement: function() {
    var self = this;
    var value = this.get('value');
    var data = null;
    if(value === null || value === undefined) {
      console.log('Value is null');
      data = [];
    } else {
      console.log('Got Value: ' + JSON.stringify(value));
      data = value;//value.getEach('data'); //for Ember Data
      var items = JSON.stringify(data);
    }

    var columns = this.get('columns');
    this.$().dataTable( {
      "bJQueryUI": true,
      "aaData": data,
      "aoColumns": columns,
      "sEmptyTable": "Loading data from server"
    });

    //this line is required for links used to make an ember transition
    this.$('a').click(function(e){e.preventDefault();});

  },
  onValueChanged: function() {
    var self = this;
    var value = this.get('value');
    var data = null;
    if(value === null || value === undefined) {
      console.log('Value is null');
      data = [];
    } else {
      console.log('Got Value: ' + JSON.stringify(value));
      data = value;//value.getEach('data'); //for Ember Data
    }
    var columns = this.get('columns');
    this.$().dataTable( {
      "bJQueryUI": true,
      "aaData": data,
      "aoColumns": columns,
      "sEmptyTable": "Loading data from server"
    });
    return;
  }.observes('value')
});

<强> HSB

<script type="text/x-handlebars">
    <h2> Welcome to Ember.js</h2>

    {{outlet}}
  </script>

  <script type="text/x-handlebars" data-template-name="index">
    {{view App.DataTableView valueBinding="model" columnsBinding="columns"}}
  </script>

<script type="text/x-handlebars" data-template-name="details">
    <h2>details</h2>

    {{controller.firstName}}
<br/>
{{#link-to 'index'}}back{{/link-to}}
  </script>