Frontend helper

Tabbli has its own integrated frontend framework which can be used for simplifying an implementation of the most common features on the site's frontend.

Installation

Tabbli provides a special helper library tabbli.js which is including by default to the site pages if you did not overload default base.html template. Otherwise, you need to add it manually.

<script src="/static/manage/javascript/tabbli.js"></script>

Because tabbli.js requires jQuery than you should add something like that if you didn't do it before:

<script src="/static/manage/vendor/jquery/jquery.min.js"></script>

Preload an URL to the DOM element

Use class __action--ajax-load to initiate loading a content from the URL which specified by data-src attribute into the DOM element when page will be ready:

<ul id="customer-toolbar" 
    class="nav navbar-nav navbar-right __action--ajax-load" 
    data-src="/customer-toolbar/">
    <li><a href="/login/">Login</a></li>
</ul>

Form submission via Ajax

Lets see at the example of "Add to cart" button implementation which could be familiar for some e-commerce or marketplace solutions:

<form class="__action--ajax-submit" 
    action="/cart/add-item/" 
    method="post" data-post-signal="update-cart">
    
    <input type="hidden" name="item-key" value="{{product.key}}">
    <input type="hidden" name="next" value="/product/{{product.key}}/">
    <input type="hidden" name="price" value="{{product.properties.price}}">
    <input type="number" name="quantity" value="1">
    <button class="btn btn-success" 
        type="submit" name="add-to-cart">
        Add to cart
    </button>
</form>

Use class __action--ajax-submit when you want to submit this form via Ajax. Attribute data-post-signal is required to force updating the cart block when new product has been added to cart. This feature will be described later.

Reload block content when something happens

In this example we use both __action--ajax-load class for preload the block content after page loading and __action--ajax-load-for-signal to initiate the block reloading when the signal is raised. Attribute data-signal is used for specify the signal.

<div id="cart-block" 
    class="__action--ajax-load __action--ajax-load-for-signal" 
    data-src="/cart/?view=block" data-signal="update-cart">
    <span class="glyphicon glyphicon-shopping-cart" 
        aria-hidden="true"></span>
    <a href="/cart/">Cart</a>
</div>

How it works. After successful form submission, from the previous example, via Ajax the signal update-cart (see data-post-signal attribute for the form) is raised. Then PCart is looking for the element with class __action--ajax-load-for-signal with the corresponding value of data-signal attribute and use the value of data-src for loading the content.

You can create a few different elements for a single signal. For example, you can also add a container for modal popup:

<div id="cart-modal-container" 
    class="__action--ajax-load-for-signal" 
    data-src="/cart/?view=popup" data-signal="update-cart"></div>

More complex example of the Ajax form

Sometimes you need to some additional actions with Ajax forms for making a more mature behavior. For example, if you have a modal popup component with a form inside and want to update the popup content after the form submission. But with Bootstrap it could be a bit tricky because it adds a div block for fade the page background outside the .modal container. It means that if you want reload a modal container with a new content we also should delete that block before. In such cases you can use data-post-remove-element attribute.

<form method="post" action="/cart/?ignore-response=yes" 
    class="__action--ajax-submit"
    data-post-signal="update-cart" 
    data-post-remove-element=".modal-backdrop">
...
</form>

If you have more than one submit buttons for the form, and need to implement different behavior for different ones on the backend, you should use data-allow-ajax attribute. In other case, due some limitation of the browser API, the request will not contain the button name.

<button type="submit" 
    name="update" class="btn btn-default" 
    data-allow-ajax="true">Update cart</button>

If you want to use Ajax form submission for some buttons and normal submission for another ones, use the data-disable-ajax attribute.

<button type="submit" 
    name="checkout" class="btn btn-primary" 
    data-disable-ajax="true">Proceed to checkout</button>

Send signal via JS

Use send_signal method:

TABBLI.send_signal('update-cart')

Load different content via Ajax depends the content of another element

Use class __action--ajax-load-for-event with attributes data-event and data-target for initiate loading a content inside the element after an event raised by another element.

<div id="shipping-form-container"
    class="__action--ajax-load __action--ajax-load-for-event __action--subform-onchange-ajax-reload"
    data-src-eval="'/checkout/shipping-form/'+$('#id_shipping_method').val()+'/'+$('#shipping-form-container').data('url-suffix')"
    data-event="change" 
    data-target="#id_shipping_method" 
    data-subform-method="post"
    data-url-suffix="{% if shipping_data != None %}?force-form-validation&{{ shipping_data|urlencode }}{% endif %}"></div>

Attribute data-src-eval allows to use JavaScript expression instead a simple string with data-src. It useful if you need to load different content in different cases.

Send ajax form without form tag

If you need to submit form data via ajax but do not able to use HTML form syntax you can use function TABBLI.ajax_send. It uses two arguments. First one it the data object. And the second one is additional attributes. For example, if we need to add a product to the wishlist we can do next:

TABBLI.ajax_send(
    {
        "item-key": "product-t-shirt-xl",
        "add-item": ""},
    {
        "action": "/wishlist/add/",
        "post-signal": "update-wishlist"
    });

Last updated