Displalay a form in light box or pop up window in view

836 views
Skip to first unread message

billmac...@gmail.com

unread,
Feb 9, 2016, 3:26:05 PM2/9/16
to web2py-users
Hello, A new user migrating from Django to web2py and absolutely loving it. A quick question. How do I use a light box or a pop up window to display a form in my view?


for example in default/index.html

{{=form}}

Want to show that form  in a pop up window.  

Massimo Di Pierro

unread,
Feb 10, 2016, 5:06:28 PM2/10/16
to web2py-users
Bootstrap3 has built-int modals: https://nakupanda.github.io/bootstrap3-dialog/
You can but {{=form}} in the body of the modal.

billmac...@gmail.com

unread,
Feb 10, 2016, 7:00:44 PM2/10/16
to web2py-users
Thank you for the answer Massimo. I did this like you said to put the form in the body in index/popup.html however, it didn't pop up like the example in the link above. Instead I got it in the same browser. I am guessing my implementation is wrong.

<div class="modal fade">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
        <h4 class="modal-title">Modal title</h4>
      </div>
      <div class="modal-body">
        
          {{=form}}
          
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div><!-- /.modal-content -->
  </div><!-- /.modal-dialog -->
</div><!-- /.modal -->

Massimo Di Pierro

unread,
Feb 10, 2016, 10:51:11 PM2/10/16
to web2py-users
I see you want a different window, not a modal.

then you have to put the form logic in its own controller action and call it from js

<button onclick="window.open("{{=URL('form_action)}}");">click me</button>

billmac...@gmail.com

unread,
Feb 11, 2016, 12:07:32 PM2/11/16
to web2py-users
Thank you for your answer Massimo. When I implemented this. 

<button onclick='window.open("{{=URL("my_view",args=something.id)}}", "mywindow");'>Apply To This Post</button>

It shows me a button and then I get redirected to another page. I just wanted a pop up window open up with a form to submit that user can move around without being redirected to another page.

Val K

unread,
Feb 11, 2016, 4:27:22 PM2/11/16
to web...@googlegroups.com
Hi!
Here is my solution.  I have modal_wrapper function. In controller file, I have two controllers -  main_page and modal_content: 



def main_page():

    main_pg=DIV(<any your content>)
    

    m_cont = LOAD(f='modal_content.load', ajax=True, ajax_trap=True  )  

    dialog = modal_wrapper(m_cont, _id='cont_id', header='Header', footer='footer')
    
    show_modal_btn = BUTTON( 'Show modal',
                                                       _type="button",
                                                       _class = "btn btn-default",
                                                     
  _onclick=""" $('#cont_id').modal('show')   """)

    #don't forget to add dialog and 
show_modal_btn to main page
    
main_pg.append(show_modal_btn)   # or main_pg.append( DIV(show_modal_btn)  ) or something else
    main_pg.append(dialog)

       return dict(main_pg = main_pg)




# keep in mind just one thing:
#   this controller is exposed by *.load, so it must return a dict of ONE element 
#   to return more than one element - wrap all in one DIV:
#   ret = DIV()
#   
ret.append( ... ) 
#   ret.append( form )  
#      
ret.append( ... )
#      return dict(ret = ret) 

def modal_content():
    
    form = SQLFORM(...) # or even 
form = SQLFORM.grid(...)

    return dict(form=form)



#
 means bootstrap 3
def modal_wrapper(content, _id, header='', footer=''):

    main_wrap = DIV('',  _class="modal fade",  _role="dialog", _id=_id, _tabindex="-1" )
    title_id = _id + '_title'
    main_wrap['_aria-labelledby']=title_id

    dialog_div=DIV('', _class="modal-dialog" , _role="document")
    content_div=DIV('', _class="modal-content")
    header_div = DIV( _class="modal-header")

    close_cross = BUTTON(
                        SPAN(XML('&times'), **{'_aria-hidden':"true"}),
                        _type="button",  _class="close",
                         data={'dismiss':"modal"},
                         **{'_aria-label':"Close"}
                         )
    title_h4 = H4( header,  _class="modal-title",  _id = title_id)
    body_div = DIV( content, _class="modal-body")


    close_btn = BUTTON('Close',  _type="button", _class="btn btn-default", data={'dismiss':"modal"})
    footer_div =  DIV( footer, close_btn, _class="modal-footer")

    # gluon all
    main_wrap[0] = dialog_div
    dialog_div[0] = content_div

    header_div.append(close_cross)
    header_div.append(title_h4)

    [content_div.append(c) for c in (header_div, body_div, footer_div)]
    return main_wrap



billmac...@gmail.com

unread,
Feb 11, 2016, 5:16:35 PM2/11/16
to web...@googlegroups.com
Thank you! Val  and the app works great.

One question:

Instead of controller, I have the button displayed in the view as:

{{=BUTTON( 'Apply',_type="button",_class = "btn btn-default",_style="background-color:green;background-image:none",_onclick=""" $('#cont_id').modal('show')   """ )}}

It works, however, I need to pass an argument to my controller "modal_content". How do I  pass a request.args(0) from my view to the controller in above? Just like I would do 

 <button onclick='window.open("{{=URL("modal_content",args=something.id)}}", "mywindow");'>Apply</button>


Since I don't see the URL or callback to the javascript. Thanks in advance.

Val K

unread,
Feb 12, 2016, 12:20:10 AM2/12/16
to web2py-users
LOAD() works like URL(), so,  to pass args/vars to modal_content you could write
m_cont = LOAD(f='modal_content.load', args=[ ],  vars={ },   ajax=True, ajax_trap=True  )  # see LOAD in web2py book

in modal_content controller there is nothing new, everything is as usual  
def modal_content():
   arg_0
= request.args(0)
   a
= request.vars.a

  

billmac...@gmail.com

unread,
Feb 12, 2016, 2:00:22 PM2/12/16
to web2py-users
In the book it says load in the view. Nothing in the controller.  I was just wondering if we can add a button in the view and call the ajax from the view with the argument. If we need to call the LOAD from the view, its

{{=LOAD('default','manage_things',ajax=True)}}

Then it fails for m_count. 

Val K

unread,
Feb 12, 2016, 2:25:36 PM2/12/16
to web2py-users

I mean passing args/vars in main_page(): 

def main_page():

    main_pg
=DIV(<any your content>)

   
   
m_cont = LOAD(f='modal_content.load', args=[ <list of your args>],  vars={<dict of your vars> },   ajax=True, ajax_trap=True  )  
   
...



But may be you want to pass something from client side, i.e. args  are defined by some user action.
What exactly do you want to do?

billmac...@gmail.com

unread,
Feb 12, 2016, 3:04:08 PM2/12/16
to web...@googlegroups.com
I said load with relation to view because I believe in the book it said that load is used when we don't want to use the extended view. In other words, a different layout. But what I have done with your code is change the contoller to be:


def main_page():
    main_pg=DIV('hello world')
    m_cont = LOAD(f='modal_content.load', ajax=True, ajax_trap=True  )  
    dialog = modal_wrapper(m_cont, _id='cont_id', header='Header', footer='footer')
    #show_modal_btn = BUTTON( 'Show modal',_type="button",_class = "btn btn-default",_onclick=""" $('#cont_id').modal('show')   """)
    #don't forget to add dialog and show_modal_btn to main page
    #main_pg.append(show_modal_btn)   # or main_pg.append( DIV(show_modal_btn)  ) or something else
    main_pg.append(dialog)
    return dict(main_pg = main_pg)


And in my view I have (I am making an example here):

{{extend 'layout.html'}}
{{=main_pg}}

{{=BUTTON( 'Apply',_type="button",_class = "btn btn-default",_onclick="$('#cont_id').modal('show')")}}

Works fine. Because I see the button and I click and see the pop up. Great. Only issue is, I need to update the table with my argument. For example:

def modal_content():
    db.mytable.id.default = request.args(0) #Just an example.
    form = SQLFORM(db.mytable) # or even form = SQLFORM.grid(...)
    return dict(form=form)


So, I need to pass that argument from my view to the controller of the form. Only thing I have at my disposal is the button. 

Валерий Кучеров

unread,
Feb 12, 2016, 3:29:47 PM2/12/16
to web...@googlegroups.com

OK,  but what do you mean under "pass that argument from my view" ?
view is processed and rendered to html page at server side,   JS runs only  on the client side.
so, if you can pass arg from veiw (i.e. arg is defined on server side), also  you can pass it in main_page():

def main_page():

    main_pg
=DIV(<any your content>)

   
   
m_cont = LOAD(f='modal_content.load', args=[1],   ajax=True, ajax_trap=True  )  # - must works, I'm sure while modal_content() runs  "int(request.args(0)) == 1"  will be true
   
...




<billmac...@gmail.com> писал(а) в своём письме Fri, 12 Feb 2016 23:04:08 +0300:

What I have done with your code is change the contoller to be:
--
Resources:
- http://web2py.com
- http://web2py.com/book (Documentation)
- http://github.com/web2py/web2py (Source code)
- https://code.google.com/p/web2py/issues/list (Report Issues)
---
You received this message because you are subscribed to a topic in the Google Groups "web2py-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/web2py/Y_TXPdRpDqQ/unsubscribe.
To unsubscribe from this group and all its topics, send an email to web2py+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
Написано с помощью почтового клиента Opera: http://www.opera.com/mail/

billmac...@gmail.com

unread,
Feb 12, 2016, 3:40:09 PM2/12/16
to web...@googlegroups.com
What I mean by passing argument from the view to the controller is this (let us consider in my view):


(1) <td width="40%"><a  href="{{=URL('my_controler_def',args=id)}}">Apply</a></td>

(2) <button onclick='window.open("{{=URL("my_controler_def",args=id)}}", "mywindow");'>Apply</button>


In the above (1) is calling that URL with an argument id. (2) is a button, when I click on that, it goes to the controller function my_controler_def, and in my_controler_def I will have that "id" argument passed on.

If I do this.

def my_controler_def():
   id = request.args(0) # the id will be here since it was passed from the view. Model-> view-> controller (MVC)
   form = SQLFORM(db.mytable)...
return locals()


I was hoping to do the same with the model. That with a button I can pass an argument from my view to the controller modal_content 
So, I need to pass that argument from my view to the controller of the form. Only thing I have at my disposal is the button.  I guess I just need to figure out how to pass the argument id into main_page(). Sorry, I am kind of new into this. So you have to excuse my ignorance. 

Dave S

unread,
Feb 12, 2016, 3:59:55 PM2/12/16
to web2py-users
On Friday, February 12, 2016 at 12:04:08 PM UTC-8, billmac...@gmail.com wrote:
Works fine. Because I see the button and I click and see the pop up. Great. Only issue is, I need to update the table with my argument. For example:

[...]

So, I need to pass that argument from my view to the controller of the form. Only thing I have at my disposal is the button. 

 Are you replacing a line in a <TD> element?

2 approaches to try are:

-- make sure that line is in the DIV the LOAD() is going to rewrite
-- LOAD into a hidden DIV, and use javascript to copy the element into the displayed DIV.

I have never tried the 2nd one, and I'm not js-savvy enough to more that wave my hands and say you find the element in the DOM and rewrite it.

The 1st is more like the normal use of LOAD(), except that you aren't putting the results into an empty container.

/dps

Валерий Кучеров

unread,
Feb 12, 2016, 4:10:00 PM2/12/16
to web...@googlegroups.com
it's easy:
1. Place modal_wrapper() function in  your_web2py_app/modUles  named 'my_util.py' (just for example) - you have to import html-helpers in it: 
from gluon.html import *
 2. In view place:
...
{{=BUTTON( 'Apply',_type="button",_class = "btn btn-default",_onclick="$('#cont_id').modal('show')")}}

{{from my_util import *}}

{{=modal_wrapper(   LOAD(f='modal_content.load', args=id,   ajax=True, ajax_trap=True  )  , _id='cont_id', header='Header', footer='footer')  }}

3. Remove all about modal from main_page() 



<billmac...@gmail.com> писал(а) в своём письме Fri, 12 Feb 2016 23:40:08 +0300:

What I mean by passing argument from the view to the controller is this (let us consider in my view):


(1) <td width="40%"><a  href="{{=URL('my_controler_def',args=id)}}">Apply</a></td>

(2) <button onclick='window.open("{{=URL("my_controler_def",args=id)}}", "mywindow");'>Apply</button>


In the above (1) is calling that URL with an argument id. (2) is a button, when I click on that, it goes to the controller function my_controler_def, and in my_controler_def I will have that "id" argument passed on.

billmac...@gmail.com

unread,
Feb 12, 2016, 4:20:30 PM2/12/16
to web2py-users
You got it to work? Because I get this:

default/main_page.html", line 83, in <module>
NameError: name 'modal_wrapper' is not defined

Controller is now:
def main_page():
    main_pg=DIV('hello world')
    #m_cont = LOAD(f='modal_content.load', ajax=True, ajax_trap=True  )  
    #dialog = modal_wrapper(m_cont, _id='cont_id', header='Header', footer='footer')
    show_modal_btn = BUTTON( 'Show modal',_type="button",_class = "btn btn-default",_onclick=""" $('#cont_id').modal('show')   """)
    #don't forget to add dialog and show_modal_btn to main page
    main_pg.append(show_modal_btn)   # or main_pg.append( DIV(show_modal_btn)  ) or something else
    #main_pg.append(dialog)
    return dict(main_pg = main_pg)


View is:
{{extend 'layout.html'}}
{{from gluon.html import *}}

{{=main_pg}}
{{id = 1}}
{{=modal_wrapper(LOAD(f='modal_content.load', args=id,   ajax=True, ajax_trap=True  )  , _id='cont_id', header='Header', footer='footer')  }}

billmac...@gmail.com

unread,
Feb 12, 2016, 4:25:18 PM2/12/16
to web2py-users
My bad. I forgot the my_util.py
Message has been deleted

billmac...@gmail.com

unread,
Feb 12, 2016, 4:36:56 PM2/12/16
to web2py-users
Look at that!

request.args(0)
'1'

Thank you Val. This is great. 

billmac...@gmail.com

unread,
Feb 12, 2016, 4:40:09 PM2/12/16
to web2py-users
I got to tell you...this is way more fun than Django. In django all I am worried using that is the framework and url redirect. Here,  the least thing to worry about is framework and I can focus more on the development and logic! Add such a helpful community. Thank you for all your help!

Ron Chatterjee

unread,
Feb 17, 2016, 9:19:09 AM2/17/16
to web2py-users
If you don't want to use the nested load, you can also do this:

form = SQLFORM(db.mytable);

dialog = modal_wrapper(form, _id='cont_id', header='Header', footer='footer')

Works just fine.
Reply all
Reply to author
Forward
0 new messages