#8735 closed bug (notabug)
activate event not fired for first tab when created
Reported by: | Cardgage | Owned by: | |
---|---|---|---|
Priority: | minor | Milestone: | 1.10.0 |
Component: | ui.tabs | Version: | 1.9.1 |
Keywords: | Cc: | ||
Blocked by: | Blocking: |
Description
In versions which used the show event, that event was fired for the first tab when it was shown the first time. Now with the activate event, that event is not fired off for the first tab - the one selected by default.
In the example provided by the jsfiddle link, I expect to see the "active" alert as soon as the page loads, not just after going to another tab and then back to the first tab.
Change History (40)
comment:1 Changed 11 years ago by
comment:2 follow-up: 3 Changed 11 years ago by
Resolution: | → notabug |
---|---|
Status: | new → closed |
This is by design. Use the create
event.
comment:3 Changed 11 years ago by
I have functionality that I want to happen when a tab is shown/activated, not when it is created. When a tab is created and then shown, it is made active. Why is it by design that the activate event is not executed when indeed a tab is being activated?
comment:4 follow-up: 35 Changed 11 years ago by
It is not being activated, it is active at the time of initialization. This is the equivalent of a change event being fired on page load for a select element because it starts with a value already selected.
comment:5 Changed 11 years ago by
Here's my working scenario: When a tab is shown, I perform methods to assemble the content of that tab. So if the activate event doesn't fire for the first tab, nothing is shown for that tab. Nor is it possible to force an activate event because the 0th tab is already active. This doesn't seem like a rare use case and I'm having trouble thinking of a use case where a user would prefer the activate event didn't occur for the tab that is active by default.
comment:6 Changed 11 years ago by
By "force an activate event", I mean to use the following code:
$(".tabs").tabs("option", "active", 0); this doesn't work
The jquery ui code recognizes that the 0th tab is already active and simply returns.
comment:8 Changed 11 years ago by
Sure. The create event fires once for the whole tab control. The content that I'm assembling involves ajax calls and other code that I want to avoid if the user doesn't require the info for that tab (load on demand).
comment:9 Changed 11 years ago by
That doesn't explain why you can't use it. The create
event tells you which tab is active (if any).
comment:10 Changed 11 years ago by
OK, so your recommendation is to handle both the "create" and the "activate" events. That works and I'll move my code to that paradigm.
Let me point out that the upgrade guide doesn't mention this discrepancy between 1.8 and 1.9 in describing the switch from "show" to "activate" http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate
Also, I'd like to reiterate that I can't see a scenario where a user would use the activate event expecting the current behavior. Anyone handling the activate event would need to handle both. Perhaps it's because I've only ever used it that way that I can't see another use for the activate event :)
comment:11 Changed 11 years ago by
Keywords: | needsdocs added |
---|
Let me point out that the upgrade guide doesn't mention this discrepancy between...
Thanks, I'll add a note about this to the upgrade guide.
Also, I'd like to reiterate that I can't see a scenario where a user would use the activate event expecting the current behavior.
Do you not see the parallel to <select>
elements? There are plenty of scenarios where users will handle the initial state fully on the server and subsequent states fully on the client.
comment:12 follow-up: 30 Changed 11 years ago by
Keywords: | needsdocs removed |
---|
I've updated the upgrade guide: http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate
comment:14 Changed 10 years ago by
I also suggest you to fix this. It confuse me for long time,for the first tab have no active event when it's created. after create ,the first tab did ACTIVED,why no event ?
comment:16 Changed 10 years ago by
This ticket should be reopened and this should be fixed because this design is seriously flawed. The answer to the question "Please explain why you can't use the create event." is this: Because I don't want to use different event to do THE SAME THINGS only because it's first tab. This is ridiculous to make me use create() event to handle something specifically for the FIRST tab and use activate() event for all other tabs. First tab is not special. It should be handled exactly like any other tabs.
My real-life case is this: I have tabs within tabs within tabs (2 to 4 levels), where 'leaf' tabs are ajax-loaded. I didn't want to initialize entire 'tab tree' in advance because there are a lot of leaf tabs and each would generate an ajax call. So I figured, I could call tabs() in a lazy-fashion for lower level tabs, on beforeActivate event, i.e. just when the user clicks given tab. The problem is that first tab clicks itself without any user activity (which is obvious) but it somehow doesn't fire beforeActivate event!
Now, if I use create() event as suggested above, it means that I'm using different event to accomplish exactly the same thing (i.e. initialize sub-tabs in this tab). Which makes the first tab somehow special by design. It does not make any sense and it's completely counter-intuitive. If I use create() event just to do something for the first tab and then I change order of my tabs (some other tab becomse the "magical" first tab) then my code will stop working correctly.
comment:17 Changed 10 years ago by
The problem is that first tab clicks itself without any user activity (which is obvious) but it somehow doesn't fire beforeActivate event!
The firs tab does not click itself. Please see my earlier comment.
comment:19 follow-up: 20 Changed 10 years ago by
This ticket should be reopened. It seems counter-intuitive that the initial tab is "active" when the tabs are first created. The initial tab should go through the same process as when the user clicks on the tab to open it.
When using remote tabs, the beforeLoad event is fired for the initial tab also. So it seems inconsistent to not also fire the beforeActivate event when not using remote tabs.
comment:20 Changed 10 years ago by
Replying to Schleis:
When using remote tabs, the beforeLoad event is fired for the initial tab also. So it seems inconsistent to not also fire the beforeActivate event when not using remote tabs.
There is no inconsistency. beforeLoad
and beforeActivate
are two very different events.
Do you find it counter-intuitive that a change
event is not triggered for <select>
elements upon page load?
comment:21 Changed 10 years ago by
I agree with all the comments. The design has been changed to bad. It became less intuitive and inconvenient.
Are there any significant advantages over the old design? If no, why not to change it back?
comment:22 Changed 10 years ago by
A <select> element has only one part and it makes no sense to load the contents of an <option> when that <option> is selected. In a tab, with a tab and the panel, it does make sense to load the content of the panel when the tab becomes active. The comparison with the <select> element is not apt. They are not equivalent controls.
comment:23 Changed 10 years ago by
Please reopen this ticket. I have exactly the same situation as described by PawelRoman.
comment:24 Changed 10 years ago by
"It is not being activated, it is active at the time of initialization." So what you are saying is during initialization you activate the tab but you do not fire the activate event. That seems odd.
The change event for a select box is a bad analogy. One is an event that happens when something CHANGES the other is an event when something ACTIVATES. But the initially selected tab is activated and therefore should have the activate event fire.
The create event should take care of things that need to happen during creation of the entire tab widget, for instance verify something exists in the DOM, it should not to load the data for a tab that is already handled when the tab activates. Even if that activation is during the initialization.
Logically you would expect the widget to initialize itself and then activate the chosen tab or activate the first tab.
comment:25 Changed 10 years ago by
Whats the situation on this bug? The first tab is activated (auto) so would like to have an event to handle it's display as with other tabs. It's inconsistent. After the content of a tab is loaded (async) and displayed you may need to run methods against it. Not being able to on the first load is frustrating and unexpected. I'm looking for a hack solution. Anyone solve this?
comment:27 Changed 10 years ago by
I would like to support the argument that the current approach is inconsistent and problematic by describing my use case and the bug that the current approach forced me to track down.
I am using tabs with panel-content that is dynamically generated when a tab is selected; I bind to beforeActivate to generate that content. The tab which is initially open is based on some system state which can be captured by an integer i: if the system is in state i then tab i should be the initially open one.
Since I have already bound beforeActivate the obvious way to set up the panel is to invoke tabs('option', 'active', i) to cause it to fill in the panel for tab i.
This works great, *unless* the system happens to be in state 0. In this case, since by your current approach tab 0 is "already active", calling tabs('option', 'active', 0) does *not* trigger a beforeActivate event, so the panel is not initialized.
I could manually initialize the panel based on i when I create the tabs, but this means I am duplicating code. If instead the beforeActivate event was triggered for whichever panel was initially selected, I would have clean code. Instead, as a quick fix, I am calling tabs('option', 'active', i-1) followed by tabs('option', 'active', i) in order to ensure that the beforeActivation event gets triggered. But this is clearly wasteful as it leads to the generation of an entire panel which is then discarded.
comment:28 Changed 10 years ago by
There's nothing forcing you to duplicate code, that's what functions are for.
comment:29 Changed 10 years ago by
I also support the argument that the current approach is inconsistent and problematic. So if 'activate' is analog to 'change' of selectbox then you need to roll back 'show' event that will triggered when the tab is shown, I sure many people do something on the tab 'show' event. Please re-open this bug and fix it!
comment:30 Changed 10 years ago by
Replying to scott.gonzalez:
I've updated the upgrade guide: http://jqueryui.com/upgrade-guide/1.9/#deprecated-show-event-renamed-to-activate
I just cannot comprehend this design decision. It seems to brake the code and make things more complicated. If one would allow the activate event to fire on the first instance of showing a tab, things would be ok.
It is clear a number of people are using these events to populate tab content. It is also possible that links to pages including anchor tags will direct a different tab to be opened at page initiation. Having to struggle with two events and with different methods of figuring out which tab has been activated makes no sense.
What makes things worse is that I cannot see many valid useful use cases for the activate event that do not fit a scenario which would involve this been fired at the appearance of the first tab.
This issue should be addressed
comment:31 Changed 9 years ago by
I think it's really counterintuitive, that the beforeActivate event is not triggered on initiation. This should be changed. After some frustration i've created a fiddle of a workaround: http://jsfiddle.net/NicoO/eq69p/6/
comment:32 Changed 9 years ago by
Got to add my voice to the crowd. This is unintuitive behavior, though at least I kind of expected it so didn't waste a lot of time identifying the problem.
And to compare the "activate" event to a select's "change" event is silly. If you wanted them to be synonymous then you should have called the event "change". "Activate" means something clearly different in this context and that includes the first tab initially activating.
comment:33 follow-up: 34 Changed 8 years ago by
OK, so how does one raise the level of this issue? Sorry, but this design is simply wrong. It is critical that event driven UI controls generate events at the right time, and are semantically relevant. CREATE and ACTIVATE are semantically different, happen logically at different times in the lifecycle of the UI, and require different responses from the application code. ACTIVATE should logically happen any time a tab is show - the "first" time is no special case, and collapsing it with CREATE is semantically incorrect. It requires every application to create a 'hack' that handles CREATE events even if that event is of no interest to the application.
This problem (of initial state and events) has been addressed many times over the years in other event-based UI systems - just take a look at the event model for Win32, Motif, Swing, SWT... similar controls (lists, tabs, etc) generate 'selected' or 'activated' events consistently, including an event that reflects initial state of the control.
Please learn something from 20 years of UI design history, this is no longer rocket science and it not even really debatable, the issue has long since been decided in favor of application simplicity and consistency.
But, I suspect adding a comment to a closed bug report is not useful... so how can the user community get this fixed??
comment:34 Changed 8 years ago by
Replying to markm:
Please learn something from 20 years of UI design history, this is no longer rocket science and it not even really debatable, the issue has long since been decided in favor of application simplicity and consistency.
See http://bugs.jqueryui.com/ticket/8735#comment:4 which shows that we're already being consistent with the environment in which we operate.
comment:35 Changed 8 years ago by
Replying to scott.gonzalez:
It is not being activated, it is active at the time of initialization. This is the equivalent of a change event being fired on page load for a select element because it starts with a value already selected.
It's not "active at the time of initialization" because it's not marked as "ui-state-active". If code change marking to "activated" it should call "activated" method.
comment:36 Changed 7 years ago by
I really hate to beat on a dead horse here. And I will not be as gratuitous as the others, but I am rather disheartened that this ticket was allowed to wither. The points brought up over the past three years are valid concerns, and the biggest argument to the contrary was that tabs are synonymous to a <select>.
The "activate" hook should be called upon activation of a tab, plain and simple. The alternative solution lacks elegance.
comment:37 follow-up: 38 Changed 7 years ago by
I want to add my support for a rethink on this issue too. I'm developing an application that uses the activate event to perform some checks and initialization whenever a panel is displayed. Everything works wonderfully except for the initial display of the first panel when the tabs widget is first created.
The create event is a useless alternative, because the tab widget is not fully initialized at this point -- specifically, when you call the 'option' function, all you get is "cannot call methods on slider prior to initialization." The first panel is not fully activated until much later.
Therefore the create event is simply not an acceptable alternative to an activation event for the first panel. It serves a completely different purpose, and is triggered far to early to be of any use to developers writing panel initialization code.
I have to agree with markm in his last comment. I do not understand the logic behind the current design. What possible reason is there for making the initial display of the first panel the widget a special case? It is the only time the activate event is not triggered when a panel is displayed. Worse, the current design is actually counter-intuitive, since the implication is that the first panel never goes through the activation process internally, which is patently not the case.
comment:38 Changed 7 years ago by
Replying to stringfold:
The create event is a useless alternative, because the tab widget is not fully initialized at this point -- specifically, when you call the 'option' function, all you get is "cannot call methods on slider prior to initialization." The first panel is not fully activated until much later.
I'm sorry, but this is just flat out wrong. The create
event is triggered after the entire initialization process has completed. Even if we did fire an activate
event during initialization, it would have to be *before* the create
event, not after. Referencing a slider instance is also meaningless since there is absolutely no context here.
comment:39 Changed 6 years ago by
OK, so your recommendation is to handle both the "create" and the "activate" events. That works and I'll move my code to that paradigm. [...] Also, I'd like to reiterate that I can't see a scenario where a developer would use the activate event expecting the current behavior. Anyone handling the activate event would need to handle both.
Pretty much nailed it. It's kinda disheartening for developers to come across such counter-intuitive & alienating behavior from jQueryUI because working around this sort of stuff is bound to lead to unnecessary over-engineering and code-bloat. Firing the activate event for the tab which is selected by-default upon creating the tab-control shouldn't be such a big a deal.
Wish I could understand why we are getting flogged like this for no reason other than pure stubborness which goes against virtually against any and all rules of thumb and common-sense followed by most if not all ui-toolkits out there. Sigh.
comment:40 Changed 3 years ago by
It's incredible I had to find this 8 years old ticket, and no solution. I solved using a wrapper to the function I was trying to trigger on both cases:
$('#tabs').tabs({ activate: function(event, tab) { onTabRender(tab.newPanel)}, create: function(event, tab) { onTabRender(tab.panel) }, });
Here is a jsfiddle showing the old, expected behavior:
http://jsfiddle.net/uuGq4/