やりたいこと
http://www.getmdl.io/components/index.html#menus-section
これをSPAの上部メニューに固定して使いたい。
バージョン
- Mithril.js 0.2.0
- MaterialDesignLite 1.0.4
View構成
※モデル部分は割愛。
ナビゲーション部分をコンポーネントとして定義する。
ナビゲーションバーコンポーネント
var NavBar = {
controller: function(args) {
var self = this;
this.current = args.page;
},
view: function(ctrl) {
return m("div",{
class: "bar"
}, [
m("button", {
class: "mdl-button mdl-js-button mdl-button--icon",
id: "menu-button"
}, [
m("i", {class: "material-icons"}, "more_vert")
]
),
m("ul", {class: "mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect", for:"menu-button", style: "width:100px;"}, [
m("li",
{class: "mdl-menu__item"},
[
m("a", {href: "/", config: m.route}, "main")
]
),
m("li",
{class: "mdl-menu__item"},
[
m("a", {href: "/detail", config: m.route}, "detail")
]
)
]
)
]);
}
};
各ページ用コンポーネントを用意する。
コンポーネントをネストして各コンポーネントにNavbarコンポーネントを持たせる。
メインページコンポーネント
var MainView = {
controller: function() {
},
view: function(ctrl) {
return m("div", {id:"main-view-main"}, [
m.component(NavBar, {page:"main"}),
m.component(MainContent)
]);
}
};
詳細ページコンポーネント
var DetailView = {
controller: function() {
},
view: function(ctrl) {
return m("div", {id:"detail-view-main"}, [
m.component(NavBar, {page:"detail"}),
m.component(DetailContent)
]);
}
};
ラウターの定義は下記のように。
ラウター定義部分
m.route.mode = "pathname";
m.route(document.body, "/", {
"/": MainView,
"/detail": DetailView
}
);
事象
ファーストビューではメニューがちゃんと出てくるが、画面遷移した先ではメニューが動作しない。
原因と解決策
ラウターによる遷移でロードがかからないと、MDLに遷移後のDOMが認識されずに動作しなくなってしまう。
なので、MaterialDesignLiteのcomponentHandler.upgradeDom()がNavbarコンポーネントの再描画時に呼ばれるように、config擬似属性に定義する。
ナビゲーションバーコンポーネント抜粋
view: function(ctrl) {
return m("div",{
class: "bar",
config: function(element, isInitialized, context) {
componentHandler.upgradeDom();// 再描画時にMDLのcomponent設定を更新する
}
}, [
config擬似属性の追加で無事にメニューが遷移後も機能するようになりました。