如何将数据(选定项目)传递给Durandal组成的详细视图?

时间:2013-03-10 21:09:45

标签: mvvm viewmodel parent-child single-page-application durandal

我已经开始使用(截至几个小时前)Durandal希望管理视图并允许在一个页面中进行合成 - 之前的方法,也使用Knockout,变得过于笨重维护在一个胖的HTML文件中。

我已经安装/设置了Durandal,我可以创建视图和视图模型 - 但是,我不知道如何将数据导入视图模型以用作基础用于新的viewmodel。

例如,我有一个“左侧导航栏”用于选择项目 - 当选择一个项目时,它会更新当前模型中可观察到的“选定项目”,但它应该加载正确的右侧的“详细视图”:因为尝试Durandal分离组件/视图的部分原因,这应该来自单独的视图/视图模型。

我已阅读包含CompositionUsing Composition的文档,但 如何将数据传递到viewmodel的方法对我来说并不清楚。看起来我可以使用现有模型的视图(在当前视图/范围中),但我真的只想使用一些当前模型数据(即id)来获取“真实”模型数据观点。

因此,我的问题;

  • 如何将初始数据(例如“选定项目”)传递给视图模型?我更喜欢使用声明性的“compose:”绑定,因为这就是制作KO的原因.KO。

  • 这种概念在这里是否正确使用/传递初始数据,还是有更好的选择?我看到“activeItem”含糊不清地提到了,但细节/用法让我很开心。


更新1:我找到How do we share the data between views/Pass the data view to view,但实际执行中缺少回复。我真的不想在父子(不同的视图/视图模型对)之间共享viewmodel,我想使用声明式方法(没有事件)。父母不需要了解孩子,但孩子需要从父母那里获得数据。


更新2:虽然上面我暗示只需要“id”,但我想要一种适用于任何基础对象的方法,路由器不一定适合。在这种情况下,深度链接不是问题。但是,如果您认为路由器 接近此方式,请发布一个参数(有详细信息)作为答案,我至少会给它一个向上投票。

3 个答案:

答案 0 :(得分:3)

如果你看一下breeze源代码,你可以看到一个主从细节方法的例子。

他们正在使用激活器来组成子视图。

https://github.com/IdeaBlade/Breeze/blob/master/Samples/TempHire/TempHire/App/viewmodels/resourcemgt.js

我不知道您是否使用微风,但该方法与您如何获取数据无关。

答案 1 :(得分:3)

关于如何使用John Papa的Eric Studio的Visual Studio模板,有关如何使用Eric Panorel的文章:http://ericpanorel.net/blog/hot-towel-spa-master-detail-scenario

简而言之,您可以利用Durandal中的路由,它会是这样的:

master.js会公开一组项目:

define(function() {
  var self = this;

  this.items = ko.observableArray([]);

  var activate = function() {
     // ... get your items
     self.items([ { id: 0, name: 'Item 1' }, { id: 1, name: 'Item 2' }]);
  }

  return {
    // some properties and ...
    activate: activate
  }
});

master.html将绑定它们并链接到详细信息视图:

<section data-bind="foreach: items">
   <a data-bind="text: name, attr: { href: '#/item/' + id() }"></a>
</section>

现在,只需使用route data参数在详细视图模型detail.js中拉出ID:

define(function() {
  var self = this;

  this.name = ko.observable();

  var activate = function(routeData) {
     var itemId = routeData.id;

     // ... get your item details
     // var details = ...

     self.name(details.name);
  }

  return {
    // some properties and ...
    activate: activate
  }
});

最后,您需要在main.js中指定路线:

define(['durandal/app', 'durandal/viewLocator', 'durandal/system', 'durandal/plugins/router'],
function(app, viewLocator, system, router) {

    //>>excludeStart("build", true);
    system.debug(true);
    //>>excludeEnd("build");

    app.title = 'Durandal app';
    app.start().then(function() {
        toastr.options.positionClass = 'toast-bottom-right';
        toastr.options.backgroundpositionClass = 'toast-bottom-right';

        //Replace 'viewmodels' in the moduleId with 'views' to locate the view.
        //Look for partial views in a 'views' folder in the root.
        viewLocator.useConvention();

        //configure routing
        router.useConvention();
        router.mapRoute('item/:id', 'viewmodels/item', 'Item', false);

        app.adaptToDevice();

        //Show the app by setting the root view model for our application with a transition.
        app.setRoot('viewmodels/shell', 'entrance');
    });
});

你去了!

答案 2 :(得分:0)

我认为可以传递任何基础对象,就像我们使用模态调用一样。 ko.compose是被动的;使用durandal路由器,您可以将数据传输到您喜欢的位置。看看我的work-around in this answer并帮助您完成。