updating menu without reloading the page

51 views
Skip to first unread message

Vlad

unread,
May 15, 2019, 7:55:26 PM5/15/19
to web2py-users
Sometimes I need to change the menu without reloading the page. 

More specifically: 

response.menu = [
    .........................
    .........................
    ('Cart (' + str(howManyItemsInCart()) + ")", False, URL('catalog','cart'), []),
]

I do control the event when the cart content changes (without reloading the page), so javascript can be inserted there; I just don't know how to "address" that menu item, as I don't manage it - web2py does - 

How would I accomplish this? ... 

Vlad

unread,
May 15, 2019, 8:43:44 PM5/15/19
to web2py-users
I didn't say it precisely. By web2py controlling it I meant that it's dynamic and changes all the time - it's not static that I could assign certain id to some item... 

Vlad

unread,
May 15, 2019, 8:58:26 PM5/15/19
to web2py-users
Never mind,
Resolved...

villas

unread,
May 16, 2019, 7:24:45 AM5/16/19
to web2py-users
Hi Vlad,
It is great that you resolved this problem. 
Many of us use this group to search and learn from each other's experiences, and it can be frustrating to read a thread of messages and then simply see 'resolved' at the bottom.
If you have time, it would be interesting and helpful to know briefly what you did.  I mean just an executive summary. 
Many thanks!

Vlad

unread,
May 16, 2019, 12:04:13 PM5/16/19
to web2py-users
Yes sure: 

My issue was the menu item with "Cart (X)" menu item where X indicated how many items were currently in the cart. Since the cart was updated with ajax calls - I needed to update that menu item. 

This is what I've changed in the menu construction in the layout.html :

          <li class="nav-item {{if _item[1]:}}active{{pass}}">
              {{if _item[0].startswith('Cart ('):}}
                  <a class="nav-link" id="CartMenuItem" href="{{=_item[2]}}">{{=_item[0]}}</a>
              {{else:}}
                  <a class="nav-link" href="{{=_item[2]}}">{{=_item[0]}}</a>
              {{pass}}
          </li>

This if-else logic takes care of giving a proper ID to the element I need to update. 

The menu.py got a small addition to its response.menu += part:

('Cart (' + str(howManyItemsInCart()) + ")", False, URL('cart','show'), []),

Where howManyItemsInCart() is communicating with the database and is located in the model file.

The catalog view got the following in the table of products:

    <td><button type="button" class="btn btn-link"
            onclick="var url='{{=URL('cart','plus',args=[item['product.id'],1],vars={'price':item['product.price'],'target':'Item'+str(item['product.id'])})}}';ajax(url,[],':eval');">Add/Remove</button></td>
    <td><div id="Item{{=item['product.id']}}">{{=isInCartRep(aBunch,item['product.id'])}}</div></td>

Clicking Add/Remove adds an item to the cart when it's not there beforehand, and removes it if it's already there. 

The function plus() which is ajax-called from the view (on Add/Remove click) returns some javascript to be executed (this allows to update multiple targets - the beauty of :eval option in ajax function):

    final_result = "document.getElementById('CartMenuItem').innerHTML='Cart (" + \
                   str(CartCount())+ \
                   ")';document.getElementById('" + \
                   target + \
                   "').innerHTML='"+result+"';"

So this updates the status (eiher 'added' or 'removed') and also the menu item text to the current cart quantity. 

It's pretty straightforward, but somehow it took me time to figure out how to address that menu item as it's created dynamically... 

This kind of stuff makes our work enjoyable :)

Thank you for the inquiry! 

villas

unread,
May 17, 2019, 7:23:35 AM5/17/19
to web2py-users
Wow thanks Vlad!  I didn't hope for such a full explanation, but this will be appreciated by anyone following the thread.
All the best.
Reply all
Reply to author
Forward
0 new messages