Closed Shoroh closed 7 years ago
I think the issue is in existed form. VueJS removes all directives from the form, like v-model, @input, etc, after it was activated. Thus 'before:cache' event stores the form without directives.
Since this time the next time when VueJS App will be activated, there won't be any directives in the form. And it won't be working.
Let me know what you think, please.
Interesting! I think you're on the right track.
What we need to do is figure out if the right HTML is cached in the beforeMount
callback. We might need to move the cache to earlier in the lifecycle of the component.
And for debugging efficiency, are you using the latest version of the mixin?
Thanks, I thought the same. And I have no idea how to deal with it at the moment :)
Yep, I use the latest version, which is 1.02 I believe.
I recently received a reply on the VueJS forum from someone who has done something similar to Chris and my mixin. You can read about it: https://forum.vuejs.org/t/using-vue-alongside-turbolinks-in-rails-5-1/9084/3
This difference between his approach and ours is that he caches the element state. Indirectly, I think this might be what you're seeing. I need to do some experiments to find out for sure.
Thanks for the link.
Unfortunately, his solution still works good only when we use templates in an application.
What we need to do is figure out if the right HTML is cached in the beforeMount callback. We might need to move the cache to earlier in the lifecycle of the component.
I think the issue is that this plugin is tearing down a DOM that is discarded during the page transition.
All we need to do is switch to using the turbolinks:before-cache
event :tada:
export default {
beforeMount: function() {
if (this !== this.$root) return;
this.__TurbolinksAdapterOriginalOuterHTML__ = this.$el.outerHTML;
var _this = this;
document.addEventListener("turbolinks:before-cache", function teardown() {
_this.$destroy();
document.removeEventListener("turbolinks:before-cache", teardown);
});
},
destroyed: function() {
if (!this.__TurbolinksAdapterOriginalOuterHTML__) return;
this.$el.outerHTML = this.__TurbolinksAdapterOriginalOuterHTML__;
delete this.__TurbolinksAdapterOriginalOuterHTML__;
},
};
If you think this is useful I'd be happy to contribute a patch.
I recently received a reply on the VueJS forum from someone who has done something similar to Chris and my mixin. You can read about it: https://forum.vuejs.org/t/using-vue-alongside-turbolinks-in-rails-5-1/9084/3
This feels like it might be a superior approach, but I worry that it's more tightly coupled to the internals of both Vue and Turbolinks making it more vulnerable to API changes over time.
@tatey We previously used turbolinks:before-cache
event. We recently just changed the code to use turbolinks:before-render
. 4d45fe63fd shows you what things used to look like.
In #8, a change was made to move the snapshot earlier in the Turbolinks event sequence to account for when Turbolinks caching is turned off. It looks to me like these problems are related.
If you can take both cases into account with your PR, we'd be more than happy to give it a review. 😄
Based on my tests this morning, I think that handling tear down inturbolinks:visit
will solve the issue.
Fixed in 1.1.1. Update the package and you should be good to go.
meta name= "turbolinks-cache-control" content= "no-cache"
in layout
this helped me
Hey Jeffrey! Thank you for the solution, it was a nice idea.
But something is still wrong, could you please take a look? I'm not sure that this is related to the Turbolinks or your solution, it might be a VueJS bug, but anyway :)
I created a really simple form using rails-slim template:
It gives us an input field we need to use with VueJs:
And typical VueJs App:
And it works well when I went to the page (two way binding, and so on, I'm able to see it in console) Until I go to another page and come back twice :)
Look:
Here you can see the initial state when the page is just opened. Then I got to another page and use browser "Back" button to return to the page with the New Account Form. When I did it the first time you still see 362 in the input field, but the VueJs App is already stopped and doesn't work. When I returned the second time you can see that the field is empty at all :)
What do you think about it? Did I miss something?