Search code examples
javascriptknockout.jsrequirejssynchronizationoracle-jet

Sync method call for a requireJS module


I am trying to build a navigation bar using Oracle Jet components, since I am concerned about the modularity of my code, I am feeding my navbar with the needed information from another module that I load using requireJS. When executed I get this error Message: Unable to process binding "foreach: function (){return pages }" Message: pages is not defined

My first guess (after using breakpoints) is that the binding is done before my variable pages gets the appropriate data. If it is the case, how can I make sure that the navbar prints only after my variable is properly initialized, if it is not, what am I doing wrong?

here's my code:

the template

<div id="topbar">
<div class="oj-sm-condense" data-bind="ojComponent:{
                component: 'ojNavigationList',
                selection: currentPage,
                navigationLevel: 'application',
                edge: 'top'}" >

    <ul id="pills" >
     <!-- ko foreach: pages -->
     <li data-bind="attr:{id:id}">
        <a data-bind="attr:{href:url}">
            <p data-bind="text:label"></p>
        </a>
    </li> 
     <!-- /ko-->
    </ul>
</div>
</div>

the JS for the template

define(['ojs/ojcore', 'knockout', 'ojs/ojnavigationlist'
], function (oj, ko) {

function homeContentViewModel(data) {

    var self = this;
    require(['banner/' + data],  function (pages) {
        self.pages=pages;
    });
}
return homeContentViewModel;
});

The data Module

define(['ojs/ojcore', 'knockout', 'ojs/ojnavigationlist'
], function (oj, ko) {

    this.currentPage=ko.observable('Page1');
    var self = this;
    var pages = [
    {id: "id1", label:"Page1", url: "#"},
    {id: "id2", label:"Page2", url: "#"},
    {id: "id3", label:"Page3", url: "#"},
    {id: "id4", label:"Page4", url: "#"},
    {id: "id5", label:"Page5", url: "#"},
    {id: "id6", label:"Page6", url: "#"},
    ];  

    return pages;
});

The index.html

<html>
<head>
    <title>navbar</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script data-main="js/main" src="js/libs/require/require.js" type="text/javascript"></script>
    <link href="css/libs/oj/v2.0.1/alta/oj-alta-min.css" rel="stylesheet" type="text/css"/>
    <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
     <div data-bind="ojModule: {name: 'path/to/template', params: 'dataModuleName'}"></div>
</body>
</html>

Solution

  • define(['ojs/ojcore', 'knockout', 'ojs/ojnavigationlist'
    ], function (oj, ko) {
    
    function homeContentViewModel(data) {
    
        var self = this;
        self.pages = ko.observableArray();
        require(['banner/' + data],  function (pages) {
            self.pages(pages);
        });
    }
    return homeContentViewModel;
    })
    

    define pages as an empty observable array before the require call