问题
I have just started playing with KnockoutJS and it it fascinating. I successfully created some templates to render two panels of an interface with "ul" nested menus inside.
Here are my templates:
<script id="menuItemTemplate" type="text/html">
<li class='${ Class }' >
<a class='${ Class }' data-bind='click: function() { viewModel.menuClicked(Id); }'>${ Name }</a>
<ul class='${ Class }' data-bind='template: { name: "menuItemTemplate", foreach: Items }'></ul>
<li>
</script>
<script id="menuTemplate" type="text/html">
<ul class='${ Class }' data-bind='template: { name: "menuItemTemplate", foreach: Items }'></ul>
</script>
<script id="consoleTemplate" type="text/html">
<div class='${ Class }' data-bind='template: { name: "menuTemplate", data: Menu }'></div>
</script>
<h2>Application Administration</h2>
<div id="console" class="console" data-bind='template: { name: "consoleTemplate", foreach: Panels }'>
</div>
And here is the simplified code for my view model:
$(function () {
var viewModel = {
"Panels": [
{
"Id" : 1,
"Class": "main",
"Menu": {
"Id": 1,
"Class": "file",
"Name": "File",
"Items": [{
"Id": 1,
"Class": "open",
"Name": "Open",
"Items": []
}]
}
}]
};
$.ajax({
url: 'console.asmx/Initialize',
type: "POST",
cache: false,
contentType: "application/json; charset=utf-8",
data: "{}",
dataType: "json",
success: function (data) {
viewModel = data.d;
viewModel.menuActive = ko.observable(false);
viewModel.currentMenu = ko.observable(0);
viewModel.menuClicked = function (id) {
viewModel.menuActive(true);
viewModel.currentMenu(id);
};
ko.applyBindings(viewModel);
}
});
});
So far, the panels and the menus are rendered fine but I now need to know which menu was clicked and show the sub-menu as well as other UI elements based on the clicked menu. The function I attached to the hyperlinks is throwing an exception: 'Uncaught ReferenceError: viewModel is not defined'
when I click on any of the hyperlinks.
I also tried to bind the visibility of sub-menus to the "currentMenu" property of the viewModel but that broke everything:
<script id="menuItemTemplate" type="text/html">
<li class='${ Class }' data-bind='visible: viewModel.menuActive && viewModel.currentMenu == Id'>
<a class='${ Class }' data-bind='click: function() { viewModel.menuClicked(Id); }'>${ Name }</a>
<ul class='${ Class }' data-bind='template: { name: "menuItemTemplate", foreach: Items }'></ul>
<li>
</script>
How can I properly bind the click event handler as well as the visibility based on the clicked menu?
回答1:
Your issue is that your variable viewModel is defined in the jQuery ready function, so the functions in your data-binds can't see it, since it is not at the global scope. Even, doing a var viewModel = {}
outside the $(function() { ... });
would work.
The way that you defined your click function looks good to me. Your visible logic though should use viewModel.menuActive()
and viewModel.currentMenu()
to access the values as they are in an expression.
Hope this helps. Would be happy to help further, if you get stuck.
来源:https://stackoverflow.com/questions/5291152/knockoutjs-tracking-menu-clicks