Невозможно активировать функцию деактивации в Дюрандале с помощью диплинкинга.

Я новичок в durandal и одностраничных приложениях, у меня возникают проблемы с запуском функций деактивации и canDeactivate. Я использую некоторый пользовательский код для создания глубоких ссылок, что, вероятно, и является причиной моей проблемы. Я следовал примеру здесь: https://github.com/evanlarsen/DurandalDeepLinkingExample см. также Подмаршрутизация Durandal (Hottowel)

Любая помощь будет принята с благодарностью.

Вот код модели представления, который я вызываю:

define([''], function () {

var vm = {
    activate: function () {
        alert('In activate!');
    },
    deactivate: function () {
        alert('In deactivate!');
    },
    canDeactivate: function () {
        alert('In candeactivate!');
    }
}
return vm;

});

Вот вьюхтмл

<div class="container-fixed"> 
 <div>
    <header>
        <!-- ko compose: {view: 'Main/Users/UsersNav'} -->
        <!-- /ko-->
    </header>
    <section id="content" class="in-users">
        <!--ko compose: { 
                            model: inUsers, afterCompose: router.afterCompose,
                            transition: 'entrance', 
                            activate: true
                        } -->
        <!--/ko-->
    </section> 
 </div>
</div>

Вот код вызова:

define(['durandal/system', 'durandal/viewModel', 'durandal/plugins/router'],
function (system, viewModel, router) {
    var App = {
        router: router,
        activate: activate,
        showPage: showPage,
        isPageActive: isPageActive,
        inUsers: viewModel.activator(),
    };
    return App;

    var defaultPage = '';
    function activate(activationData) {

        defaultPage = 'ManageUsers';
        App.inUsers(convertSplatToModuleId(activationData.splat));

        router.activeItem.settings.areSameItem = function (currentItem, newItem, data) {
            if (currentItem != newItem) {
                return false;
            }
            else {
                App.inUsers(convertSplatToModuleId(data.splat));
                return true;
            }
        };
    }

    function showPage(name) {
        return function () {
            router.activate('#/Users/' + name);
            //router.navigateTo('#/Users/' + name);
            App.inUsers(convertNameToModuleId(name));
        };
    }

    function isPageActive(name) {
        var moduleName = convertNameToModuleId(name);
        return ko.computed(function () {
            return App.inUsers() === moduleName;
        });
    }

    // Internal methods
    function convertNameToModuleId(name) {
        return 'Main/Users/' + name + '/' + name;
    }

    function convertSplatToModuleId(splat) {
        if (splat && splat.length > 0) {
            return convertNameToModuleId(splat[0]);
        }
        return convertNameToModuleId(defaultPage);
    }
});

РЕДАКТИРОВАТЬ: (Главная главная страница)

 function activate() {

        // my convention
        router.autoConvertRouteToModuleId = function (url) {
            return 'Main/' + url + '/index';
        };

        return router.activate('Home'); 
    }

Nav HTML for master:
<div class="btn-group">
                     <a href="#/home" class="btn btn-info">HOME</a>
                     <a href="#/resources" class="btn btn-info">RESOURCES</a>  
                     <a href="#/users" class="btn btn-info">USERS</a>               
 </div>    


Main master: 
  <div class="container-fixed"> 
   <div>
    <header>
        <!-- ko compose: {view: 'Main/masterNav'} -->
        <!-- /ko-->
    </header>
    <section id="content" class="main">
        <!--ko compose: {model: router.activeItem, 
            afterCompose: router.afterCompose,
            transition: 'entrance'} -->
        <!--/ko-->
    </section>        
    <footer>
        <!--ko compose: {view: 'Main/masterFooter'} --><!--/ko-->
    </footer>
  </div>
 </div>   

person Mark Beattie    schedule 05.07.2013    source источник


Ответы (1)


Проблема, с которой вы сталкиваетесь, связанная с невозможностью деактивировать ваши подмаршрутизированные представления, заключается в том, что viewmodel.activator() observable, возвращаемый этим методом, применяет шаблон активатора в durandal. Этот наблюдаемый ожидает модуль amd, а не строку.

Несмотря на то, что строка работает нормально, потому что привязка compose знает, как загружать модули на основе строки... активатор модели представления не знает, как загружать модули из строк.

Итак, вам нужно передать фактический модуль наблюдаемому.

Пример, который я создал ранее, просто использовал строку, поэтому он будет составлять представление... но шаблон активатора не работает, если есть только строка. Таким образом, вместо этого вам придется require вставить все ваши модули amd подмаршрута в вызывающий код, а затем вместо использования метода convertSplatToModuleId создать новый метод, который возвращает правильный модуль.

Итак, что-то вроде этого:

define(['durandal/system', 'durandal/viewModel', 'durandal/plugins/router'],
function (system, viewModel, router) {
    var App = {
        router: router,
        activate: activate,
        showPage: showPage,
        isPageActive: isPageActive,
        inUsers: viewModel.activator(),
    };
    return App;

    var defaultPage = '';
    function activate(activationData) {

        defaultPage = 'ManageUsers';
        convertSplatToModuleId(activationData.splat).then(function(activeModule){
            App.inUsers(activeModule);
        })


        router.activeItem.settings.areSameItem = function (currentItem, newItem, data) {
            if (currentItem != newItem) {
                return false;
            }
            else {
                convertSplatToModuleId(data.splat).then(function (module) {
                    App.inUsers(module);
                });
                return true;
            }
        };
    }

    function showPage(name) {
        return function () {
            router.activate('#/Users/' + name);
            //router.navigateTo('#/Users/' + name);
            convertNameToModuleId(name).then(function(module){
                App.inUsers(module);
            });            
        };
    }

    // Internal methods
    function convertNameToModuleId(name) {
        return system.acquire('Main/Users/' + name + '/' + name);
    }

    function convertSplatToModuleId(splat) {
        if (splat && splat.length > 0) {
            return convertNameToModuleId(splat[0]);
        }
        return convertNameToModuleId(defaultPage);
    }
});
person Evan Larsen    schedule 05.07.2013
comment
Большое спасибо, Эван, именно то, что мне было нужно, очень признателен. - person Mark Beattie; 15.07.2013
comment
В связи с этим вопросом у меня теперь есть проблема, когда я нажимаю на свои основные (не подпрограммированные) страницы, когда я нажимаю на них, я не получаю вызовы методов candeactivate и deactivate. Пожалуйста, смотрите код выше - person Mark Beattie; 16.07.2013
comment
Было бы лучше задать это как новый вопрос. - person RainerAtSpirit; 16.07.2013
comment
Это связано с этим вопросом, я надеюсь, что Эван узнает. - person Mark Beattie; 16.07.2013
comment
проверьте, является ли наблюдаемый объект, привязанный к обработчику привязки durandal compose, модулем amd, а не строкой. - person Evan Larsen; 17.07.2013
comment
Привет, Эван, спасибо, что ответили мне, раздел редактирования выше содержит всю необходимую информацию, пожалуйста, поправьте меня, если я ошибаюсь. Настройка в основном такая же, как и проект, который вы собрали. Я считаю, что он просто отображает активный элемент, хотя я не совсем уверен, как это исправить. // мое соглашение router.autoConvertRouteToModuleId = function (url) { return 'Main/' + url + '/index'; }; вернуть router.activate('Дом'); - person Mark Beattie; 17.07.2013
comment
Я не уверен. Можете ли вы заархивировать свое решение и бросить его куда-нибудь? - person Evan Larsen; 18.07.2013
comment
Привет, Эван, я отправил тебе электронное письмо. Пожалуйста, проверьте папку нежелательной почты. - person Mark Beattie; 19.07.2013