Hey there!
Love the library, but I seem to keep running into an issue where the Barba.HistoryManager.currentStatus() object is always returned undefined. Whereas prevStatus() seems to work perfectly.
I'm following one of your demo's code in order to use a variety of transitions.
Barba.Pjax.getTransition = function() {
var transitionObj = FadeTransition;
if (Barba.HistoryManager.currentStatus().namespace === "homepage") {
transitionObj = HomeTransition;
}
return transitionObj;
};
Is there a preferred way for determining what transition to use when you want separate pages to use unique animations?
Is there any chance we could add a demo with namespaces/views? I'm finding them difficult to use correctly given most pages will have two on a page initially.
Thanks!
Hi @destefanis !
Are you sure that Barba.HistoryManager.currentStatus() returns undefined, or it's just the .namespace value?
In the second case, it's normal.
When .getTransition is called, the next page is not loaded yet, that means that we don't know the data-namespace yet on the next container.
Usually I use different solutions:
1. by URL
You can make a check on Barba.HistoryManager.currentStatus().url to choose what Transition to use.
cons: could be tricky to keep track of the URL for a multilanguage / CMS driven site
2. by namespace
You can make a generic Transition, that waits newContainerLoading to be resolved, at that point .namespace will be populated and you can continue the transition accordingly.
cons: You need to wait the loading of the next page before starting the transition
3. by latest clicked element
You may want to save the latest clicked element
let lastClickEl;
Barba.Dispatcher.on('linkClicked', (el) => {
lastClickEl = el;
});
then, in .getTransition, decide the transition based on this.
How I structure my transitions:
I use commonJS modules for all my project, and I have all my transition in separate files.
To each transition I implement a valid() method, that could return true or false, based if that transition has the right or not to be executed.
A typical valid function may look like this:
valid() {
const prev = Barba.HistoryManager.prevStatus();
return prev.namespace === 'page-blabla' && (window.innerWidth > 800);
}
and in my .getTransition I do something like:
getTransition() {
if (FromHomeSlider.valid()) {
return FromHomeSlider;
}
if (PortfolioToCaseStudy.valid()) {
return PortfolioToCaseStudy;
}
if (CaseStudyReadMore.valid()) {
return CaseStudyReadMore;
}
if (CaseStudySibling.valid()) {
return CaseStudySibling;
}
return FadeTransition;
}
This structure helps me to be very flexible, and to use that three different technique to choose if that particular transition needs to run or not.
Hope this reply fits your needs.
Cheers!
Informative and thorough response! I might suggest adding something like this to the documentation. However, this is perfect, I appreciate the help.
Hi everyone,
I'm trying to do like @luruke with a valid() method in each transition. I think it's very clever.
So I declare a prev and a next var with Barba.HistoryManager.prevStatus and Barba.HistoryManager.currentStatus for each in this method. So I can manage my transitions very precisely (home to page, post to page, etc).
My transition is a promise of newContainerLoading but Barba.HistoryManager.currentStatus stay undefined. I don't understand why.
With newContainerLoading the new content is load and HistoryManager has been updated, isn't it? So currentStatus should not be undefined, right?
Thanks for the help. 馃槉
Hi @19h47 , Do you have an example you can share?
Even a small one, just to make it more clear :)
Thanks
Yes, of course.
So I have my transition.
var FadeTransition = Barba.BaseTransition.extend({
start: function() {
Promise
.all([this.newContainerLoading, this.fadeOut()])
.then(this.fadeIn.bind(this));
},
fadeOut: function() {
},
fadeIn: function() {
},
valid: function() {
var prev = Barba.HistoryManager.prevStatus();
var next = Barba.HistoryManager.currentStatus();
console.log(prev.namespace + ' to ' + next.namespace);
return prev.namespace === 'home' && next.namespace === 'page'
}
});
And then:
Barba.Pjax.getTransition = function() {
if (FadeTransition.valid()) {
return FadeTransition;
}
};
Is my logic is correct?
Hey @19h47,
basically the namespace is grabbed when the next paged is loaded (it's the data-namespace on the container), so, you can't know in advance the namespace until newContainerLoading is resolved.
Does it makes sense?
Ah ok, I'm too fast. 馃槄
I have to think differently. Thank you so much for your time, and for Barba.js!
Really enjoying Barba!
I've come up with a technique for managing transitions that I wanted to share. Curious if anyone else has used this technique. Would really appreciate any feedback!
// All transitions are managed by a single reducer transition
Barba.Pjax.getTransition = transitionReducer
const map = {
default: fade,
home: {
single: fade,
},
single: {
home: slideUp,
},
}
// once the newContainerLoading promise resolves, we can check if a custom transition
// is defined in the map. If it's not, use the default transition defined in the map.
const transitionReducer = () => Barba.BaseTransition.extend({
start() {
// maybe show a spinner or some loading indicator here
this.newContainerLoading.then(() => {
const from = Barba.Pjax.History.prevStatus().namespace
const to = Barba.Pjax.History.currentStatus().namespace
return ((map[from] && map[from][to]) || map.default)(
this.oldContainer,
this.newContainer,
this.done.bind(this)
)
})
}
})
// then define transitions like so
function fade(oldContainer, newContainer, done) {
// call done when transition is complete
}
function slideUp(oldContainer, newContainer, done) {
// call done when transition is complete
}
Thank you @mikehwagz for sharing this 馃憤
This is indeed a good approach when need to have different animation from -> to.
Only drawback is that you must wait the next page to be loaded to know which transition to use, but in most cases it shouldn't be a problem.
Thanks for the feedback @luruke! You've done an excellent job with this library. Hopefully the loading isn't too much of an issue on slower connections.
@luruke
Looking back at the way how you structure your custom transitions.
_You may want to save the latest clicked element
let lastClickEl;
Barba.Dispatcher.on('linkClicked', (el) => {
lastClickEl = el;
});
then, in .getTransition, decide the transition based on this._
And then you are checking what was clicked and in your get transition you set this:
_getTransition() {
if (FromHomeSlider.valid()) {
return FromHomeSlider;
}
if (PortfolioToCaseStudy.valid()) {
return PortfolioToCaseStudy;
}
if (CaseStudyReadMore.valid()) {
return CaseStudyReadMore;
}
if (CaseStudySibling.valid()) {
return CaseStudySibling;
}
return FadeTransition;
}_
Are you running the Barba.Dispatcher.on('linkClicked', (el)... in each of the functions you have made?
Got this working by following the above example using
const prev = Barba.HistoryManager.prevStatus();
and
const next = location.pathname.substr(1);
To get the URI, I can then check the previous and next pages to make sure the correct transition is fired.
Why do you need the "prevStatus" for a transition that is for the next page?
@Guaby If you only want a certain transition to occur when going from a specific page to another then you need to check what the previous page/namespace was.
That way the specific transition won't happen if you visit the page from every single other page, only the ones you choose.
I've read all the above comments and understand that the currentStatus.namespace is yet undefined when getTransition is being called.
Still, I' confused about this:
As you can see, in the first line inside the {} brackets, the namespace is undefined, as expected. But when opening the dropdown arrow (in chrome by the way) I can see the current namespace defined.
Can someone explain me why so?
@josias-r
Chrome shows the objects in the console per reference.
When you console.log, in that precise moment the value is undefined.
Then when you expand the object you see the new namespace. That's because the object was modified
@luruke
That makes sense, thank you very much, I was thinking it might be something like that.
Most helpful comment
Hi @destefanis !
Are you sure that
Barba.HistoryManager.currentStatus()returnsundefined, or it's just the.namespacevalue?In the second case, it's normal.
When
.getTransitionis called, the next page is not loaded yet, that means that we don't know thedata-namespaceyet on the next container.Usually I use different solutions:
1. by URL
You can make a check on
Barba.HistoryManager.currentStatus().urlto choose what Transition to use.cons: could be tricky to keep track of the URL for a multilanguage / CMS driven site
2. by namespace
You can make a generic Transition, that waits
newContainerLoadingto be resolved, at that point.namespacewill be populated and you can continue the transition accordingly.cons: You need to wait the loading of the next page before starting the transition
3. by latest clicked element
You may want to save the latest clicked element
then, in
.getTransition, decide the transition based on this.How I structure my transitions:
I use commonJS modules for all my project, and I have all my transition in separate files.
To each transition I implement a
valid()method, that could returntrueorfalse, based if that transition has the right or not to be executed.A typical
validfunction may look like this:and in my .getTransition I do something like:
This structure helps me to be very flexible, and to use that three different technique to choose if that particular transition needs to run or not.
Hope this reply fits your needs.
Cheers!