Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

same route reload #890

Closed
sasi513 opened this issue Oct 6, 2014 · 8 comments
Closed

same route reload #890

sasi513 opened this issue Oct 6, 2014 · 8 comments

Comments

@sasi513
Copy link

sasi513 commented Oct 6, 2014

Here is my iron-router route

    this.route("video",{
      path:'/video/:_id/:slug',
       waitOn: function() {
         Session.set("currentTitle",this.params.slug);
         Session.set("currentVideoId",this.params._id);
         console.log("waitOn");
       },
      onBeforeAction: function () {
      },
      action:function(){
        console.log("action");
        this.render();
      },
      data:function(){
        console.log("data");
            var video= Videos.findOne({_id: this.params._id});
             if(video){
              console.log("set the url");
              Session.set("currentVideoURL",video.videourl);  
              Session.set("thumb",video.thumbs);  
            }            
            return {
              video:video
            };
      }
});

On the template rendered event I'm calling some meteor method and processing the result

Template.video.rendered=function(){
        console.log("rendered event");
        var id=Session.get("currentVideoURL");
        Meteor.call("getdata",id,function(e,d){
            //processing
        });
};

and in my html, I'm displaying some relative videos, on click of those videos I want to open the same page with this video data

but the video variable data in router's data method is resetting and the rendered event is not firing(I didn't seen render event in console),

I want the page to open as we are coming from another url, I want all the events to be fired.

How to acheive this?

@sasi513 sasi513 closed this as completed Oct 7, 2014
@sasi513 sasi513 reopened this Oct 7, 2014
@MaximDubrovin
Copy link

Another use case where need soft same route reload:

I have already published post

/post/:_id

Then I go to edit it:

/post/:_id/edit

Think about it as a draft version only visible for post owner.

Simple post document looks like:

{
    title: {
        published: 'published title',
        unpublished: 'unpublished drafted version'
    },
   content: {
        published: published content,
        unpublished: unpublished content
    } 
}

On /post/:_id/edit all changes automatically saves to .unpublished fields.

Data on that route not reactive due heavy custom html inserting with animations which hard to manage with reactivity. And there no sense for reactivity anyway. I'm only one viewer of my draft.

By not reactive I mean all Collection.find() in data() function includes {reactive: false}

At some point I decided that I want to cancel changes and roll back to already published version.

I mean that data from .published fields syncs to .unpublished fields.

I click some «Cancel changes» button and some cancelChanges(postId) function that syncs published fields to unpublished.

Since data ins note reactive there no visible changes on /post/:_id/edit for me

So I try to run Router.go('albumEdit', {_id: 'thisAlbumId'})

But nothing happens since I'm directing IR to the same location. But what IR doesn't know that data for rendering is changed.

Current solution:
window.location.reload();

But it is harm for single page app. Bad for app that imitates native on some platform. And it doesn't guarantees that data will be written to database since on reload there will be new sub from db. In some soft IR reload version I'll be able to reuse cache where changes applied 100% sure.

What I wish I'll be able to do:

Router.go from /post/123/edit to /post/123/edit

Without resubscribing but with re-running data() and this.render()

I have another idea is to put data function in relation with some my reactive variable which invalidates on «Cancel changes» button click and this will cause re-run data() and action() once again.

@MaximDubrovin
Copy link

Router.current().render().data() do the job for me.

It re-runs route and resubscribes but now I think it's okay if internally Meteor works this way:

I click «Cancle changes»

I update documents → update goes to local cache → update goes to database

Then I run Router.current().render().data() and route re-runs, resubscribes.

If Meteor preserve order that update goes firstly and subscription will be 100% on update docs then all is okay.

Visually it looks very smooth instead of location.reload();

@MaximDubrovin
Copy link

False alarm. It doesn't work.

@MaximDubrovin
Copy link

Ah-ha. I need to specify template to render.

Router.current().render(Template.content_for_albumEdit).data();

Same main template that I specify in tamplate: field.

I run it from event handler on button click. Run when ever you want.

@tmeasday
Copy link
Contributor

@MaximDubrovin - The decision was made at some point that you can't route to the same URL. I think your idea of putting a reactive dep in the data() function to re-run it is the best idea. Calling render() and data() on the route controller seems brittle and dangerous.

@tmeasday
Copy link
Contributor

@sasi513 - regarding the original problem -- the issue here is that IR takes pains to not-rendered a template if it doesn't have to. You'd have the same issue if you routed between URLs that rendered the same template (so it's not the shared route that's the problem).

The simplest solution to your problem is to use an auto run in rendered that uses Template.getData() to re-run everytime the route's data changes.

@tmeasday tmeasday added this to the Requires Triage milestone Oct 19, 2014
@cmather
Copy link
Contributor

cmather commented Oct 26, 2014

@tmeasday is right that you should use the autorun technique inside the rendered callback to run some code every time the data changes.

But this also brings up an interesting point about two urls going to the same controller and not wanting to rerun helpers. The logic I'm using currently looks at whether the route is the same. But I think it should actually be looking at whether the controller is the same.

EDIT: To be more clear, I recently implemented a change where if you navigate from one route to the next and it's the same route, don't create a new controller instance and instead just reconfigure the existing instance with the new url and params.

@hadynz
Copy link

hadynz commented Jun 9, 2015

The decision was made at some point that you can't route to the same URL.

@tmeasday Are you able to point me to where abouts this behavior is taking place? I would like to somehow suppress it for a given number of client routes in my app. Using a reactive var in data() could potentially be the way to go around this problem, however, I am wary on the complexity this would introduce in places were this is required.

My use case is that when a user goes to a URL such as /edit/1, a modal edit form is shown to the user. The user then has the option to close the modal, and re-open it again; hence the need to be able to rerun the same route.

Creating a solution based on client routes only, and without a mixture of events is the idea solution that I am trying to achieve = simplicity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants