问题
I am working on a SPA that I would like to use multiple master views. Here is my use case:
I have a user that has a profile page. Within that profile page I would like to be able to display a couple of different views, ie. details, works, contact info, etc. I need to be able to deep link to each of these views. Each of these views must display the basic user data from the master layout view.
It is my understanding that I should be using compose for this and I have a bit of code that seems to work, however, I want to be able to pass data from the "secondary shell" down to the actual sub view. It seems that the splat data is not passed along to the activate method of the sub viewmodel.
In my "master" viewmodel I have created an observable called activeView that contains a string corresponding to a sub viewmodel (viewmodels/user/details). I then have a knockout statement that is as follows:
<!-- ko compose: {
model: activeView(),
activate: true
} --><!-- /ko -->
How can I pass data to the sub view? Or is there a better way to do this?
Thanks in advance!
回答1:
According to me, ko.compose is not so dynamic and seems to work like Razor's layout. With durandal it's better to make separate views as you can and then, link them to the router. I'm working with John Papa's Hot-Towel template; My proposal concerns passing data (more than id) with durandal router and knockout.
When initializing your app (shell.js, main.js, ...) map your routes somewhere (shell.js or main.js) with settings for eventually filtering. For routes which will transport data, built them with the (:id) proposal
router.mapRoute('view/:id', moduleId, 'Customer Details', false);
Where and when some routes needed You can have a look to Joseph Gabriel's solution (https://stackoverflow.com/a/16036439/2198331) to filter your routes for use where and when you need them. After you filter the routes, you can hack routeInfo to transport your parameters (strings or objects like selectedItem).
arearoutes = ko.utils.arrayFilter(router.visibleRoutes(), function (route) {
// mgpe has been set at app init
return route.settings.mgpe === 112;
});
extend your routeInfo from filter's results with the data you want to transport
areaRoutes.forEach(function(ar){
ar.myItem = mydata; // or vm.selectedItem(); DEPARTURE LUGGAGE
}, areaRoutes);
Your (myItem) is now attached to these routes as so as you like This or these route(s) will carry your data with them and will never lost it unless you updated the same object of the router (myItem)
function activate(adata){
vm.arrivalData(adata.routeInfo.myItem); // ARRIVAL LUGGAGE are here
}
a route can carry nested routes Useful for nested context like nested menus; you can play with children routes by preparing the travel when a parent route is active :
router.activeItem.settings.areSameItem = function (currentItem, newItem, activationData) {
mybag = activationData.routeInfo; // TRAVEL (current) LUGGAGE are present here
}
N.B. : before use this work-around you have to consider the security issue and as I'm new to durandal I don't know if this will not bring serious consequences at the router's route life-cycle. Also be aware with object's names as its stay permanently during the router's route living.
回答2:
How about you create a user object and require it within each of your viewmodels? The easy thing would be to attach it to the app (i.e. app.user = ) Changes made to any of the observables in said user object will update to each of the views and viewmodels within your SPA.
That way you're leveraging the capabilities of the knockout library's sub/pub
来源:https://stackoverflow.com/questions/16431512/durandal-multiple-master-pages