Send combination of two input values with htmx - javascript

I'm writing a simple website with Django and I decided to try htmx library in client side to load html fragments. Now I want to sort lists by different fields, ascending and descending. I have something like this:
<div class="col-auto">
<div class="input-group input-group-sm">
<select id="np-sort-key" name="key" class="form-select">
<option value="publish_date" selected>Publish date</option>
<option value="title">Title</option>
</select>
<button class="btn btn-outline-dark" type="button">
<span class="bi bi-sort-down"></span> <!-- bi-sort-up for Asc icon -->
</button>
</div>
</div>
I want to add/replace the order_by=<order><key> query parameter to/in the current url (For example /articles?page=2&order_by=-publish_date.) and send it back to Django view both on "select" change and "button" click. The endpoint returns a Html I want to swap it with another Html node with Htmx. (Note that span class should be changed on button click to show sorting is Asc or Dsc)
Is it possible using htmx? If not, simple Javascript solutions are welcome.

You could solve it like this:
You use
<form hx-get="...">
...
<input type="hidden" name="order_by">
</form>
Then you can display the user a nice icon for sorting. If the user clicks on the icon, you update the hidden input via JS.

The easiest approach would be to construct the URL server side based on the input values and then push it using the HX-Push response header:
https://htmx.org/reference/#response_headers

From what I understood of htmx documentations, htmx provides us two tools to send custom values:
hx-vals that lets you add custom parameters to the ongoing request. These parameters are in the form of a Json object and their values could be either static or dynamic (returned from a JS function). For example:
<div hx-get="/list" hx-vals='js:{"order_by": concatSortOrderAndKey()}'>
hx-include that adds values of the elements specified by a query selector to the ongoing request.
In case of my problem, in addition to #guettli answer, I could set htmx parameters on "select" and "button" tag and use hx-vals to calculate new order_by value. (also by using hx-boost, hx-* stuff could be set only on outer enclosing elements). But overall, I think the hidden input was a better solution.

Related

Use Product Variants Select in Cart Prestashop

I'm developing a cross sell module that will display products in cart that you can add to cart by clicking the button add to cart.
I need to take consideration of product variants (attributes).
I've already find out how to add the add to cart button to the cart page thanks to this code :
<form action="{$urls.pages.cart}" method="post" id="add-to-cart-or-refresh">
<input type="hidden" name="token" value="{$static_token}">
<input type="hidden" name="id_product" value="{$product->id}" id="product_page_product_id">
<span class="remove-from-cart">
<button class="btn btn-primary add-to-cart" data-button-action="add-to-cart" type="submit"
{if (!$product->checkQty(1))} disabled {/if}>
<i class="material-icons float-xs-left">shopping_cart</i>
{l s="Add to cart" d='Shop.Theme.Actions'}
</button>
</span>
</form>
But what I need now is to update the display price depending about the value chosen with the select option value dropdown set as on my product page and use the attribute id selected in order than when the user click on the add to cart button, it add to cart the product with the good attribute and not the default one
I'm sure that is from js script that the price is updated but I don't really find out which function is in charge of this
This is the select option as asked
<div class="clearfix product-variants-item">
<span class="control-label">ATTRIBUTE_GROUP_NAME</span>
<select class="form-control form-control-select" id="group_ATTRIBUTE_GROUP_ID" data-product-attribute="ATTRIBUTE_GROUP_ID" name="group[ATTRIBUTE_GROUP_ID]">
<option value="ATTRIBUTE_ID" title="ATTRIBUTE_NAME" selected="selected">ATTRIBUTE_NAME</option>
</select>
</div>
the solution is not very simple but is achievable, the same way as prestashop works on product page, you have to ajax refresh your content on the attribute change. We developed a complex upselling module on checkout using the same method and it works good.
The logical steps are:
-> Select value is changed
-> submit the data via ajax
-> get the fresh and updated data, best choice for me is to render your module view again and get an html as response
-> replace your content with the new html
Another way, not tested because little bit more complex in my opinion, could be to store in javascript all the data about all the variations/combinations and handle the logic there to get the price data you need on every change. A problem with this solution is that the data could be not always updated because stored locally.
I hope my hint helps, I wanted to comment but my ranking is still too low and I have to reply instead.
Simone

How To Update Hidden Field In Django Form

I am trying to figure out the best approach to modifying a hidden django form field. Or if it's even possible. I had my HTML setup to accomplish this very task and it was working perfectly. However, in order to prevent multiple submissions I had to change my HTML and now I am unable to figure out how to pass a value via an HTML button depending on what the user clicks on.
Previously, I had two buttons defined as outline below:
<button type="submit" class="button1" name="status" value="Saved"><h3 class="txtalgn4">Save</h3></button>
<button type="submit" class="button2" name="status" value="Submitted"><h3 class="txtalgn4">Submit</h3></button>
As stated above, this worked perfectly for the purpose of passing a value to an attribute for my model. The value of status was saved as expected depending on which button the user clicked on.
Now I have updated the buttons to type="button" in response to this issue that I opened up today...How To Prevent Double Submit With Form Validation
I tried using the following code:
<button type="button" class="button1" name="status" value="Saved"><h3 class="txtalgn4">Save</h3></button>
<button type="button" class="button2" name="status" value="Submitted"><h3 class="txtalgn4">Submit</h3></button>
And then I also changed the status field to {{ status.as_hidden }} in my HTML to get the value. This only works if I hardcode the status value in my database structure. I need to be able to get this value dynamically depending on what the user clicks. Is JQuery with Ajax the right approach for this? Is there some simple way to modify the hidden field depending on which button the user clicks?
Is there some better way to go about trying to get this field in a hidden manner? As stated above the HTML way with type="submit" worked perfectly, but caused problems when I was trying to prevent the user from double submitting the form. As in all things programming I solved one problem and created another.
Thanks in advance for any thoughts.
Keep using two submit buttons like you were. But instead of disabling the buttons, you disable the whole form from submitting if once submitted.
First, give your form a unique html ID.
<form id="myform">
...
</form>
<!-- JS code -->
<script type="text/javascript">
$('#myform').on('submit', function(e) {
if ($(this).hasClass('submitted')) {
// prevent submission
e.preventDefault();
return;
}
$(this).addClass('submitted');
});
</script>

GTM Event on Content

I can't see to find an answer to this one anywhere. I'm trying to setup a trigger and event tag in Google Tag Manager to fire whenever content is present. Essentially, I am creating a simple event in Google Analytics for Product Views. The developer for this site is expensive, so I'd like to handle it purely in GTM.
One piece of content that only exists on product pages is the submit on the cart button.
Can anyone recommend a method to inject some code with GTM to fire when content exists so I can trigger a tag off it?
Here is the html in and around the cart button. I'm thinking that I can fire something when class="clsAddCartRight" exists or the submit - either one:
<div id="variationGroup" class="clsViewItemVariationGroup clsOverflow" style="clear:both;">
<div class="clsViewItemVariationList clsOverflow" style="width:200px;margin:0 auto;">
<select name="item_variations" id="item_variations_496" onchange="getDetails()">
<option value="1606" selected="selected">Medium</option>
<option value="1607">Large</option>
</select>
</div>
<div class="clsItemSaleDetailBlockBottom">
<form name="purchaseItemFrm" id="purchaseItemFrm" action="http://www.runwaycrush.com/marketplace/cart.html" method="post">
<input type="hidden" name="item_id" id="item_id" value="1602">
<input type="hidden" name="c_action" id="c_action" value="add">
<input type="hidden" name="item_ref" id="item_ref" value="kanduclothing">
<input type="hidden" name="item_matrix_id" id="item_matrix_id" value="4721">
<div class="clsItemCartBlock clsFloatRight" id="addCartButton" style="margin:20px auto 0px; width:318px;">
<div class="clsAddCartLeft">
<div class="clsAddCartRight">
<input type="submit" name="add_to_cart" id="add_to_cart" value="ADD TO CART">
</div>
</div>
</div>
</form>
</div>
</div>
You can use a DOM type variable in GTM and use the "CSS Selector" option to select the element by classname (if the same class is there multiple times it will pick the first occurence). If you set the attribute name field to "class" the value for that variable will be the value of the class attribute.
Actually I think it would be better if you use the button itself and look for the "id" attribute with the value of "add_to_cart", because ids are unique per page (or should be).
However you also need an event to trigger a tag.
The value will be available only after the DOM has rendered. So the easiest way would be to set up a pageview and set the trigger type to "DOM Ready" and have if only fire when the value of your DOM variable matches the classname (or id respectively) of the button.
However if your product page urls follow any recognizable pattern it would be a lot better to use a url filter in a pageview trigger. That way you could have your tags trigger on pageload, which for many tags is much preferable.

How to add another option to website and

I have a javascript that shows and hides options from a html form. What I am trying to do is be able for the user to add a new category and then write that into the database as an option and add that subject to the option form.
Here is an example of the html code,
<select id="team1" name="team1" style="display:none">
<option value="subcat1">subcat1</option>
<option value="subcat2">subcat2</option>
<option value="subcat3">subcat3</option>
I then want them to be able to add another subcat4 via the website.
the javascript i'm using is an if statement with show and hides from different selects.
The user needs to be able to enter the category name and add it to the relevant select.
Currently im unsure on how to get this to add and save the new subcat4 to the database and to the html.
Any help would be appreciated.
When you first load the page you construct the select element by using the values stored in the database.
Then you can have a form that posts the filled info and stores subcategories into the database. This form may contain the identifier of your select for knowing in which select you are assigning the new option. It could be in a hidden input.
here comes a simple example of that form
<form method='post' action='/your/action/here' >
<input type='hidden' name='main_category' value='team1' />
Subcategory: <input type='text' name='subcategory' value='' />
<input type='submit' name='submit_btn' value='submit' />
</form>
You could also do it without page refresh by using an ajax post (this should be your next step, make it first work the simple way) to store the info and then by appending the option to your select using javascript. Check the jquery append or the appendChild() if you are not using jquery.
With jquery you can do this code to append new child in your select element.
$('#team1').append('<option value="subcat4">subcat4</option>');

How do I make a drop down list selection update an image on a web page?

On the site http://www.gofundme.com/sign-up/ they have the cool ability to select your currency underneath where you enter an amount. When you change the currency it changes the symbol beside the amount you type in.
I'd like to do something similar with my website but don't have much of a clue about how to even go about it. Can anyone point me in the right direction?
Go easy on me guys; I've done a bit of website making before but never anything too spectacular.
The code on that site is all client-side, and is fairly simple.
You click the link, it invokes Javascript that shows the selection popup div.
When you select an item on the selection popup div, it also calls Javascript. That javascript modifies:
The original div's label text for the amount field (i.e. the big €)
The text below that describes your currently selected currency type (the one that pops up the div)
The data in the hidden form field, with the selected currency type
...and closes the popup div.
Edit: Apparently you also need the jQuery library in order to use the code in my answer :) You could substitute your own Javascript code, and get identical results, but it wouldn't look exactly like the code below.
Here is the code, ripped straight off "view source":
The amount box:
<div class="amt_box bg_white">
<label class="currency-display">$</label>
<input type="text" name="Funds[goalamount]" value="" class="big-field"
tabindex="1" />
</div>
The link that opens the popup div:
<h4>Display: US Dollars</h4>
The popup div:
<div class="currency currency-select-div" style="position:absolute; display:none;margin-left:45px;">
<ul>
<li>$ USD Dollar</li>
<li>$ CAD Dollar</li>
<li>$ AUD Dollar</li>
<li>£ GBP Pound</li>
<li>€ EUR Euro</li>
</ul>
</div>
The hidden form field:
<input type="hidden" id="currencyfield" value="USD" name="Organizations[currencycode]" />
The Javascript (jQuery) code that binds it all together:
$('.currency-select').click(function() {
$('.currency-select-div').show();
return false;
});
$('.currency-item').click(function() {
$('.currency-select-div').hide();
$('.currency-display').text($(this).attr('title'));
$('.currency-select').text($(this).text());
$('#currencyfield').val($(this).attr('code'));
You're going to want to uniquely identify the text that you're trying to change with your drop-down list first.
<span id="currencySymbol">$</span>
Then you're going to want to create a drop-down list that has the values you want.
<select id="currencySelect">
<option value="$">Dollars</option>
<option value="£">Pounds</option>
<option value="€">Euros</option>
</select>
Then you need to use JavaScript to change the value of the text based on the value of the drop-down.
document.getElementById('currencySelect').onchange = function(){
document.getElementById('currencySymbol').innerHTML = this.value;
}

Categories