1

I have an view that extends the current project view, where we add multiple tabs (notebook pages) to show information from other parts of a project.

One of these pages is an overview page that summarizes what is under the other tabs, and I'd like to link the headlines for each section directly to each displayed page. I've currently solved this by using the index of each tab and calling bootstrap's .tab('show') method on the link within the tab:

$(".overview-link").click(function (e) {
    e.preventDefault();
    var sel = '.nav-tabs a:eq(' + $(this).data('tab-index') + ')';
    $(sel).tab('show');
});

This works since I've attached a data-tab-index="<int>" to each header link in my widget code, but it's brittle - if someone adds a tab later, the current indices will be broken. Earlier I relied on the anchor on each tab, but that broke as well (and would probably break if a new notebook page were inserted as well).

Triggering a web client redirect / form link directly works, but I want to show a specific page in the view:

this.do_action({
    type: 'ir.actions.act_window',
    res_model: 'my.model.name',
    res_id: 'my.object.id',
    view_mode: 'form',
    view_type: 'form',
    views: [[false, 'form']],
    target: 'current'
});

Is there any way to link / redirect the web client directly to a specific notebook page tab through the do_action method or similar on FormWidget?

ChesuCR
  • 9,352
  • 5
  • 51
  • 114
MatsLindh
  • 49,529
  • 4
  • 53
  • 84

3 Answers3

1

If I understood well you want to select the tab from the JavaScript (jQuery) FormWidget taking into account that the id could change if anybody install another module that adds another tab

Solution 0

You can add a class to the page in the xml form view. You can use the id of the element selected by this class name in order to call the right anchor and select the right tab item. This should happen when the page is completely loaded:

<page class="nb_page_to_select">
$('a[href=#' + $('.nb_page_to_select').attr('id') + ']').click()

NOTE: As you have said the following paragrah I assume that you know where to run this instruction. The solution I suggest is independent of the index.

This works since I've attached a data-tab-index="<int>" to each header link in my widget code, but it's brittle - if someone adds a tab later, the current indices will be broken. Earlier I relied on the anchor on each tab, but that broke as well (and would probably break if a new notebook page were inserted as well).

Solution 1

When the page is loaded you can get the tab list DOM object like this:

var tablist = $('ul[role="tablist"]')

And then you can click on the specifict tab, selecing by the text inside the anchor. So you don't depend on the tab index:

tablist.find('a:contains("Other Information")').click()

I think if you have two tabs with the same text does not make any sense, so this should be sufficient.

Solution 2

Even if you want to be more specific you can add a class to the notebook to make sure you are in the correct notebook

<notebook class="nt_to_change">

Now you can use one of this expressions in order to select the tab list

var tablist = $('div.nt_to_change ul.nav-tabs[role="tablist"]')

// or

var tablist = $('div.nt_to_change ul[role="tablist"]')

Solution 3

If the contains selector doesn't convince you because it should be equal you can do this as well to compare and filter

tablist.find('a').filter(function() {
    return $.trim($(this).text()) === "Other Information";
}).click();

Where "Other Information" is the string of the notebook page

ChesuCR
  • 9,352
  • 5
  • 51
  • 114
  • I have updated my answer, please send me feedback @MatsLindh – ChesuCR Dec 31 '17 at 11:32
  • These options sounds like good solutions - I'll try them when I'm back at the office on Tuesday and get back to you! Thank you! I thought about selecting based on text, but since there's a lot of whitespace around the text - and contains _may_ select the wrong tab if you have names that can be contained in other tab names, such as "Orders" and "Expired Orders". I think using a class name or a data attribute on the page element sounds like the best solution, so I'll try that first. – MatsLindh Dec 31 '17 at 12:31
0

I didn't tried the solution I'm giving to you, but if it doesn't work at least may be it makes you come up with some idea.

There's a parameter for XML elements named autofocus (for buttons and fields is default_focus and takes 1 or 0 as value). If you add autofocus="autofocus" to a page in XML, this page will be the displayed one when you open the view.

So, you can try to add this through JavaScript, when the user clicks on the respective link -which honestly, I don't know how to achieve that by now-. But you can add a distinctive context parameter to each link in XML, for example context="{'page_to_display': 'page x'}". When you click on the link, I hope these context keys will arrive to your JS method.

If not, you can also modify the fields_view_get method (here I wrote how to do that: Odoo - Hide button for specific user) to check if you get the context you've added to your links and add the autofocus parameter to the respective page.

forvas
  • 9,801
  • 7
  • 62
  • 158
  • `autofocus` doesn't really work for javascript based applications where there isn't an explicit page load, so I don't think that will work - but feel free to prove me otherwise! The fields_view_get method is specific to the server - I'm working in a javascript based context (i.e. in a FormWidget). I do know in JS which link has been clicked, but I need to tell the Odoo web client to display a particular tab in the notebook - hopefully without hacking it with the index as I've done now. – MatsLindh Dec 21 '17 at 18:27
-1

As you said:

This works since I've attached a data-tab-index="" to each header link in my widget code, but it's brittle - if someone adds a tab later, the current indices will be broken.

I assume that your app allow multi-user interaction in realtime, so you have to integrate somewhere in your code, an update part function.

This function will trig if something has changed and cleanout the data to rebuilt the index in order to avoid that the current indices will be broken.

A. STEFANI
  • 6,707
  • 1
  • 23
  • 48
  • But these indices are generated by Odoo when the tabs are created - I've had issues where reinstalling the module on a clean install would change the id's, then suddenly have them changed back later. This isn't stable, and isn't something I can generate from my code (i.e. rebuild the index - these id's are created by Odoo, unknown to my module except for running it and seeing what is being shown) – MatsLindh Dec 30 '17 at 20:45