Grid links in component do not open in new window properly

135 views
Skip to first unread message

Jim Karsten

unread,
Nov 12, 2014, 9:19:17 PM11/12/14
to web...@googlegroups.com
If I open page links or column header links of a grid into a new page (eg right click, Open in new Tab/Window) it works fine. If the grid is in a component, the page that opens has no formatting. It's opening just the component.

To simulate:

# model
db.define_table('item', Field('amount', 'integer'), migrate=True)
if db(db.item).count() == 0:
from gluon.contrib.populate import populate
populate(db.item, 100)

# controller (controllers/default.py)
def inner():
    response.generic_patterns = ['html', 'load']
    grid = SQLFORM.grid(db.item)
    return locals()

def outer():
    return dict()

# View (views/default/outer.html)
{{extend 'layout.html'}}
{{=LOAD(c='default', f='inner', extension='load', ajax=True)}}


View the inner page directly ((http://my.domain.com/app/default/inner) and right click on the 'page 2' link and select 'Open in new Tab' and all is good. A page opens as expected on page 2.
 
View the outer page (http://my.domain.com/app/default/outer) and it looks the same, everything works generally the same, except now when I right click on 'page 2' link and select 'Open in new Tab' the resultant page does not display properly. There is no html from layout.html, only the raw component is displayed.

Any ideas on how to prevent that?
Jim

Leonel Câmara

unread,
Nov 13, 2014, 7:37:49 AM11/13/14
to
The problem is that URL, when an extension is not specified, inherits it from the current URL which is .load in the case where they are loaded in components with extension='load'.

The thing is, this need to be load, otherwise inner will use the generic HTML view extending layout.html and you don't want to have a layout inside your layout when you're not opening in a new window.

So basically inner needs to detect whether it's really a component or not, generally that's what the extension is for. The only way I can remember to do this would be with stupid javascript hacks. For instance, you could make an inner.load view like this:

{{=grid}}


<script>
$
('.web2py_grid a').each(function() {
   
if (typeof $(this).attr('href') !== 'undefined') {
        $
(this).attr('href', $(this).attr('href').replace('.load', '.html'));
        $
(this).click(function(e) {
           
if (e.which == 1) { // If we're left clicking
               
if(e.ctrlKey) { // ctrl key being pressed also means new tab
                    window
.open($(this).attr('href'));
                    return false;
                } else {  // We really want to stay in the component
                    $
(this).attr('href', $(this).attr('href').replace('.html', '.load'));
               
}
           
}
       
});
   
}
});
</script>


What this does is make all links have a .html extension, then if the user is left clicking it makes it .load again. Yep, it's ugly, but you asked for it.

[edit] Added a return false that was needed.

Anthony

unread,
Nov 13, 2014, 9:33:04 AM11/13/14
to web...@googlegroups.com
A simpler option might be to check whether the request is being made via Ajax, and conditionally change the view:

def inner():
    response
.view = 'default/inner.load' if request.ajax else 'default/inner.html'

    grid
= SQLFORM.grid(db.item)
   
return locals()

In that case, the .html view should extend the layout. Alternatively, you could have a single view with a conditional extends:

{{extend 'layout.html' if not request.ajax else None}}

Note that the view cannot be compiled in that case.

Anthony

Leonel Câmara

unread,
Nov 13, 2014, 9:42:00 AM11/13/14
to web...@googlegroups.com
Actually, Anthony's suggestion is better, I clearly shouldn't be here without my dosage of coffee, do that.

Jim Karsten

unread,
Nov 14, 2014, 11:30:01 AM11/14/14
to web...@googlegroups.com
I think I can make this work. Thanks for your help Anthony and Leonel.

Jim

fbenh...@gmail.com

unread,
Jan 17, 2016, 12:05:53 PM1/17/16
to web2py-users
Could you indicate whether what you did work, please?

I've the same problem, when using appadmin/manage, which internally uses the smartgrid:
opening a link in a new tab does not work (nor do the next / previous buttons).

The problem I have when trying to implement Anthony's solution is the following:
in some cases the grid component returns an image (when a field of the table is an image) and this image is retrieved without ajax.

One dirty way to fix this consists in behaving differently depending on the query to the smartgrid component, as it seems that these image queries are of the form .../table/download/....

But is there a better solution?
Reply all
Reply to author
Forward
0 new messages