Передача данных между представлениями в Durandal

У меня есть вид с сеткой, откуда я запускаю другой вид в новом окне. Родительское представление должно передавать данные дочернему представлению, и его нельзя передать в виде строки запроса, поскольку оно довольно большое. Я не могу использовать родной модальный. Я просто использую window.open и не создал настраиваемый модальный контекст. Вещи, которые я пробовал

<сильный>1. Попытался заполнить скрытые элементы поля в новом окне, используя что-то вроде кода ниже

var popup = window.open('/#/viewname');
popup.onload=function(){document.findbyid('hiddenfield')= newvalue };

Я использую страницу-заставку для отображения загрузки в Durandal, при загрузке нового окна маршрутизатор все еще перемещается, и я получаю документ страницы-заставки.

<сильный>2. Пробовал запросить родительское представление в дочернем представлении, а затем получить данные родительского представления, используя что-то вроде кода ниже

define(['viewmodels/parent'],function ('parent'){

function activate(){
localvariablevalue= parent.observable;



}

return{
activate:activate
}

});

Я получаю parent.observable как неопределенное. Скорее всего, это вырвано из контекста, так как это новое окно.

3. Пробовал одноэлементный файл global.js и требовал его как в родительском, так и в дочернем, но я думаю, что это также теряет контекст, поскольку я получаю неопределенность даже при таком подходе

Любые идеи о том, как этого добиться... если это можно сделать с помощью версии 1.2? Если это может быть достигнуто путем создания пользовательского модального контекста, то может ли кто-нибудь дать несколько советов о том, как определить функцию addContext для нового окна.


person shai    schedule 05.07.2013    source источник
comment
Моей тупости нет предела!! Как указал Райнер в своем третьем редактировании win =window.open ; win.targetwinvariable=value работает просто отлично... Никаких сложных подходов не нужно... 2 дня насмарку!!   -  person shai    schedule 09.07.2013


Ответы (2)


При использовании window.open создается независимый экземпляр #/viewname SPA, который не имеет отношения к первому SPA. Если вам действительно нужно открыть новое окно, вам нужно будет изучить другие способы обмена информацией между окнами, например, например. локальное хранилище.

Но вам, вероятно, лучше переосмыслить требования и посмотреть, не сможете ли вы достичь цели с помощью модальных окон.

Редактировать на основе комментария: это не имеет никакого отношения к тому, что Дюрандаль теряет контекст, это примерно window.open не открытие в том же сеансе. см. напр. window.open не открывается в том же сеансе

Edit2 В качестве альтернативы вы можете использовать параметр #/viewname во втором окне vm.activate для получения данных либо напрямую с сервера (если применимо), либо через веб-хранилище, например localstorage или sessiontorage из первого браузера.

Edit3 Я быстро проверил, можно ли это сделать, используя только window.open. Протестировано в Firefox/Firebug. Я бы по-прежнему рекомендовал проверять ссылки на веб-хранилище. чтобы убедиться, что это работает кросс-браузер.

Перейдите по адресу http://dfiddle.github.io/dFiddle-1.2/#/, откройте консоль и создайте глобальную переменную:

window.myVar = {complex: true};

создать новое окно

var myWindow = window.open('http://dfiddle.github.io/dFiddle-1.2/#/view-composition');

вернитесь к первой консоли и создайте свойство myvar в myWindow

myWindow.myVar = myVar;

переходим в консоль второго окна и проверяем

myVar // output {complex: true}

Альтернатива, которую я предложил, использует уникальное хэш-значение, которое вы передаете во второе окно, а затем либо извлекает сложные данные (которые можно добавить в виде строки запроса) как часть обратного вызова activate. Данные могут храниться на сервере или через веб-хранилище.

person RainerAtSpirit    schedule 05.07.2013
comment
Так вы говорите, что Дюрандаль теряет контекст? Я ошибаюсь, думая, что немодальные окна могут быть созданы с сохранением модального контекста, чтобы Durandal знал об этом? - person shai; 08.07.2013
comment
Спасибо за ответ Райнер. В моем случае сессия не может играть роли. Открытие нового окна и доступ к значениям переменных javascript... здесь не задействован сеанс сервера. И window.open не меняет сеанс нормально. В вашем примере это так, потому что они используют встроенный элемент управления вместо браузера. На данном этапе единственное решение для меня, кажется, состоит в том, чтобы эмулировать новое окно, изменив модальный стиль Дюрандаля. - person shai; 08.07.2013
comment
Данные хранятся в первом окне в js var, мне просто нужно передать их во второе окно. Итак, вы предлагаете передать его как строку запроса и получить в событии активации? Если вы это не сработаете для меня, как я уже упоминал в своем первоначальном посте. - person shai; 08.07.2013

Райнер спасибо за попытку помочь. Следующий код будет генерировать максимизированные модальные окна. На данном этапе я отказываюсь от этого решения и передаю свои данные в качестве активации в showModal. Это точная копия модального контекста по умолчанию с небольшими вариациями CSS. Но публикую его, если это кому-то поможет.

<сильный>1. CSS

.modalHostMax {
    top: 0px;
    left: 0px;
    right: 0px;
    bottom: 0px;
    position: fixed;
    opacity: 0;

    -webkit-backface-visibility: hidden;

    -webkit-transition: opacity 0.1s linear; 
    -moz-transition: opacity 0.1s linear; 
    -o-transition: opacity 0.1s linear;
    transition: opacity 0.1s linear;
}
.modalMax {

    width: 100%;
    height: 100%;


}

2. Новый модальный контекст

   var addContext = function (contextName) {
            modalDialog.addContext(contextName, {
                blockoutOpacity: .2,
                removeDelay: 200,
                addHost: function (modal) {
                    var body = $('body');
                    var blockout = $('<div class="modalBlockout"></div>')
                        .css({ 'z-index': modalDialog.getNextZIndex(), 'opacity': this.blockoutOpacity })
                        .appendTo(body);

                    var host = $('<div class="modalHostMax"></div>')
                        .css({ 'z-index': modalDialog.getNextZIndex() })
                        .appendTo(body);

                    modal.host = host.get(0);
                    modal.blockout = blockout.get(0);

                    if (!modalDialog.isModalOpen()) {
                        modal.oldBodyMarginRight = $("body").css("margin-right");

                        var html = $("html");
                        var oldBodyOuterWidth = body.outerWidth(true);
                        var oldScrollTop = html.scrollTop();
                        $("html").css("overflow-y", "hidden");
                        var newBodyOuterWidth = $("body").outerWidth(true);
                        body.css("margin-right", (newBodyOuterWidth - oldBodyOuterWidth + parseInt(modal.oldBodyMarginRight)) + "px");
                        html.scrollTop(oldScrollTop); // necessary for Firefox
                        $("#simplemodal-overlay").css("width", newBodyOuterWidth + "px");


                    }


                },
                removeHost: function (modal) {
                    $(modal.host).css('opacity', 0);
                    $(modal.blockout).css('opacity', 0);

                    setTimeout(function () {
                        $(modal.host).remove();
                        $(modal.blockout).remove();
                    }, this.removeDelay);

                    if (!modalDialog.isModalOpen()) {
                        var html = $("html");
                        var oldScrollTop = html.scrollTop(); // necessary for Firefox.
                        html.css("overflow-y", "").scrollTop(oldScrollTop);
                        $("body").css("margin-right", modal.oldBodyMarginRight);
                    }
                },
                afterCompose: function (parent, newChild, settings) {

                    var $child = $(newChild);
                    var width = $child.width();
                    var height = $child.height();



                    $child.attr('class', 'modalMax');
                    $(settings.model.modal.host).css('opacity', 1);

                    if ($(newChild).hasClass('autoclose')) {
                        $(settings.model.modal.blockout).click(function () {
                            settings.model.modal.close();
                        });
                    }

                    $('.autofocus', newChild).each(function () {
                        $(this).focus();
                    });
                }
            });
        };

<сильный>3. В целевом представлении убедитесь, что для минимальной высоты контейнера установлено значение $(document).height()

<сильный>4. Чтобы использовать просто установите пользовательский контекст, вызвав addContext('yourcontextname'). Затем создайте модальное окно - app.showModal('viewname',{data},'yourcontextname')

person shai    schedule 08.07.2013