shai
shai

Reputation: 111

Passing data between views in Durandal

I have a view with a grid from where I launch a different view in a new window. The parent view needs to pass data to the child view and it cannot be passed as a query string since it is pretty large. I cannot use a native modal. I am just using window.open and have not created a custom modal context.Things that I have tried

1. Tried populating hidden field elements in the new window using something like the code below

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

I am using a splash page to display loading in durandal , onload of the new window the router is still navigating and I get the splash page document

2. Tried requiring the parent view in the child view and then grabbing the parent view data using something like the code below

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

function activate(){
localvariablevalue= parent.observable;



}

return{
activate:activate
}

});

I get parent.observable as undefined. More than likely it is out of context as this is a new window.

3.Tried a singleton global.js file and requiring it in both parent and child but I think that is also losing context as I get undefined even with that approach

Any ideas on how to achieve this.. if it can be achieved using v 1.2 ? If it can be achieved by creating a custom Modal context then can someone give some pointers on how to define the addContext function for a new window .

Upvotes: 0

Views: 1449

Answers (2)

RainerAtSpirit
RainerAtSpirit

Reputation: 3723

By using window.open an independent instance of a #/viewname SPA gets created that has no relation to the first SPA. If you really have to open a new window than you'd need to look into other ways to exchange information between windows like e.g. localstorage.

But you're probably better off rethinking the requirements and see if you can't achieve the goal with modals instead.

Edit based on comment: That has nothing to do with Durandal loosing context, it's about window.open not opening in the same session. see e.g. window.open doesn't open in same session

Edit2 As an alternative you might use the param #/viewname in the second windows vm.activate to retrieve the data either from the server directly (if applicable) or via webstorage e.g. localstorage or sessionstorage from the first browser.

Edit3 I did a quick test do see if that can be accomplished using window.open alone. Tested in Firefox/Firebug. I would still recommend to checkout the links to webstorage to ensure that this is working cross browser.

Go to http://dfiddle.github.io/dFiddle-1.2/#/, open up a console and create a global var:

window.myVar = {complex: true};

create a new window

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

go back first console and create a property myvar on myWindow

myWindow.myVar = myVar;

change to the console of the second window and check

myVar // output {complex: true}

The alternative that I was suggesting uses the unique hash value that you pass in to the second window and then either retrieves the complex data (that can be added as query string) as part of the activate callback. The data could be stored on the server or via webstorage.

Upvotes: 1

shai
shai

Reputation: 111

Rainer thanks for trying to help out. The following code will generate maximised modals. At this stage I am resigning to this solution and passing my data as activation in showModal. It is an exact copy of the default modal context with minor css variations.But posting it if it helps someone out.

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.New modal context

   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. In your target view make sure that the container min-height is set to $(document).height()

4. To use just set custom context by calling addContext('yourcontextname').Then create your modal - app.showModal('viewname',{data},'yourcontextname')

Upvotes: 1

Related Questions