Background
I am trying to write a Single Page Application (SPA) which has a Master -> Detail structure so clicking on items in a screen filter down to other listings/details. For example I have the following
I am trying to write this with Oracle Jet. I have created 3 modules
In each module, it uses a 3rd party library to get data from the server. For the first 2 modules, the main module gets a basic the list of items to display (i.e. CategoryList gets the list of category IDS) and its sub-module gets the full information for that specific item (for example CategoryListItemModule calls the server to get all the display information for that category)
CategoryListModule.html
<oj-bind-for-each data="[[categoryIds]]" as="categoryId">
<template>
<div data-bind="ojModule:
{name: 'CategoryListItemModule',
params:{categoryId: categoryId} }">
</div>
</template>
</oj-bind-for-each>
CategoryListItemModule.html
<div >
<div data-bind="text:categoryTitle"></div>
<div data-bind="text:text:categoryDescription"></div>
</div>
Router in main.js
I have created a Router in my main.js as follows
self.router = oj.Router.rootInstance;
self.router.configure({
'categoryList':
{label: 'CategoryListModule',
value: 'CategoryListModule',
isDefault: true},
'recipeList':
{label: 'RecipeListModule',
value: 'RecipeListModule'},
'recipeDetails':
{label: 'RecipeDetailsModule',
value: 'RecipeDetailsModule'}
});
var viewModel = {
router: router
}
Bootstrap.whenDocumentReady().then(
function() {
ko.applyBindings(viewModel);
}
);
ISSUE
I do not know how to code the user clicking on a specific category and take the user to the recipe list.
In Vue/Angular/React I coded it with a link around the html for the Category List Item that told the router where to go, for example in Vue it was something like the following
<router-link :to="{ name: 'recipesList', params: { categoryId: categoryId}}">
<div>{{categoryTitle}}</div>
<div>{{categoryDescription}}</div>
</router-link>
I see examples with the Router, but it seems tied to Jet Components which I am not using. For example, in the Cookbook it has the Simple Router example
HTML
<oj-bind-for-each data="[[router.states]]">
<template>
<oj-option value="[[$current.data.id]]">
<span><oj-bind-text value="[[$current.data.label]]"></oj-bind-text></span>
</oj-option>
</template>
</oj-bind-for-each>
JAVA SCRIPT
var router = Router.rootInstance;
router.configure(
{
'pref': { label: 'Preface', value: 'This is the Preface.',
isDefault: true },
'chap1': { label: 'Chapter 1', value: 'This is Chapter 1.' },
'chap2': { label: 'Chapter 2', value: 'This is Chapter 2.' },
'chap3': { label: 'Chapter 3', value: 'This is Chapter 3.' }
});
var viewModel =
{
router: router
};
I presume in this example Oracle Jet framework is handling on the onclick of an item in the lists by the "oj-option" component as i see no "onClick" code anywhere.
I see you can do event binding in Jet and in code instigate the router to route but I am sure this can not be the correct solution (for example, i could wrap my html with a or and have an onClick listener in the JavaScript to tell the router to go to the next screen.
Any suggestions on how to implement such navigation would be greatly appreciated.
UPDATE
I have got a lot further with this. I have found out how you can use code to tell the router to route. So in my "CategoryListItemModule.html" I have added an "onClick" to the div
<div on-click="[[onClicked]]>
<div data-bind="text:categoryTitle"></div>
<div data-bind="text:text:categoryDescription"></div>
</div>
I have changed my router config in "main.js" to
self.router = oj.Router.rootInstance;
self.router.configure({
'categoryList':
{label: 'CategoryListModule',
value: 'CategoryListModule',
isDefault: true},
'recipeList/{id}':
{label: 'RecipeListModule',
value: 'RecipeListModule'},
'recipeDetails':
{label: 'RecipeDetailsModule',
value: 'RecipeDetailsModule'}
});
In "CategoryListItemModule.js" I get the router and implement the "onClicked" method
define(['ojs/ojcore', 'ojs/ojrouter', 'knockout', '],
function (oj, Router, ko) {
function AViewModel(params) {
....
router = Router.rootInstance;
....
this.onClicked= function(event) {
router.go('recipes/'+ categoryId);
}
....
};
....
Now when the user clicks on a specific category in the category list (with say id 123), the "onClicked" function is called which tells the router to route to "/recipeList/123 which should load the RecipeListModule with the ID 123 accessible from inside that module.
However this is still not working correctly as the Jet fails to find RecipeListModule .js/RecipeListModule.html as the path it uses to try and find those files in my project has an extra "recipes" in the path. I have logged the following separate for this issue to simply this final piece.
Oracle Jet routing is adding extra folder in path when trying to get child module files
The update in my original post shows the solution for creating a master -> detail SPA.
The remaining issue i had which i put in a separate post has a solution also.