Use Product Variants Select in Cart Prestashop - javascript

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

Related

Send combination of two input values with htmx

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.

Several radio button groups in nested ng-repeat, but only last group shows the value

I have a page where I want to update a form with several radio buttons. I query an api, and use the returned array of objects to populate the current values for the radio buttons. The problem that I have is that only the last set of radio buttons actually shows the value. This is the code that I have (I am using [[ and ]] for the start and end symbols for angular):
<fieldset data-ng-repeat="s in sections">
<div class="form-group">
<div class="col-md-12">
<h2>[[ s.section.name ]]</h2>
</div>
</div>
<!-- Field Item -->
<div class="form-group m-b-20 bg-light" data-ng-repeat="f in s.fields">
<div class="col-md-12 m-b-30">
<h4>[[ f.field.name ]]</h2>
<input type="text" data-ng-model="f.comments" class="form-control input-md underline" placeholder="Comments">
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="pass" class="form-control" data-ng-model="f.field_condition">
<label class="eval-pass"><i class="fa fa-check-circle green"></i> Pass</label>
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="fail" class="form-control" data-ng-model="f.field_condition">
<label class="eval-fail"> <i class="fa fa-exclamation-circle red"></i> Fail</label>
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="n/a" class="form-control" data-ng-model="f.field_condition">
<label class="eval-na"> <i class="fa fa-circle blue"></i> N/A</label>
</div>
<div class="col-sm-3">
<input type="radio" name="section-[[s.section.section_id]]-field-[[f.field.field_id]]" value="caution" class="form-control" data-ng-model="f.field_condition">
<label class="eval-caution"><i class="fa fa-exclamation-triangle yellow"></i> Caution</label>
</div>
</div>
[[ f.field_condition ]]
<hr>
</fieldset>
So basically, I have several sections, and each section has several fields. Each field has it's own radio button group (I am using the section and field ids to name the radio group). What I currently see is only the last field in each section actually shows the selected radio button. The other fields don't have any selection, even though the value for ng-model definitely does (I am showing the value of f.field_condition just to make sure there is a value).
For each field, I can see that the model is set. And if I select a value manually, I can see that the model changes, so it seems to me that the model is setup correctly. I just don't know why it won't initially show as selected for all rows but the last one.
I should also mention that if I save the form even with the missing radio button selections, the database is updated properly (it doesn't set the values to null, and if I manually change the selected value, it is updated in the db as well).
Does anyone have any ideas? Thanks!
EDIT
Here is a fiddle for this, although, it is working as expected in the fiddle. http://jsfiddle.net/dq8r196v/367/
I tried using the static data that I used in the fiddle, but I am still having the same problem. Does anyone know if this could be a CSS problem? The radio buttons are styled, and I didn't write the HTML or CSS.
UPDATE
I am still having this issue, so I built a new angular app and only used the code that is included in the fiddle that I have created. I am having the same problem with this new app, even though the same code works in the fiddle. I really don't understand what's happening here, but if anyone could shed some light, I would really appreciate it.
I have literally copied and pasted the code from my fiddle into a new angular app, and only the last group of radio buttons in each section is showing the value in the app.
Here is my complete code for the new angular app if someone else wants to try it out and see exactly what is happening: https://pastebin.com/qSR33yfM
I created the app on a single page for simplicity.
Here is the link to a pastebin with the exact json that I am using in my app: https://pastebin.com/utfVVQfT
I fixed the problem you're having by simply adding an array of objects ($scope.values) representing the different radio button options, and using an ng-repeat to create your radio buttons. See the following for the updated code: https://pastebin.com/s3hNzaXX
I know there are semantics around ng-repeat creating new $scopes, and imagine there is a conflict in scopes with your nested ng-repeats where it's binding to the radio buttons incorrectly and at a scope different than you want (the section level ng-repeat).
To confirm this suspicion, you could convert all of your interpolations in the code to use functions and console.log s and f at different points and confirm that field_condition is being set at a level you didn't intend.
Either way, it' best practice to create your radio buttons through data (and using ng-repeat), as is done with the $scope.values array, and a good side effect to doing this is not only can you update the different value options using data through AJAX or however you would like, but you won't have weird angular scoping issues as you're experiencing in your current code above.

Javascript to do realtime calculations of add ons to custom packages during form stage

Still learning so hopefully i can explain the best i can without confusing everyone!
Seems fairly basic, The form i have puts together a package for the user, basically how shopping cart software would work.. The user can select what they need and go to checkout, Well during this process on the (3 out of 5) page, There is a section for the user to ADD Extras to their package. The original designer that helped is no longer able to do so. The code he used is as follows:
This is an item selected as an extra (So should add £6.80 to total price instantly when clicked the {ADD} Button or in this exact instance deduct the amount from total price when clicked {Remove} )
<input type="hidden" name="NNRSU" value="" /></div>
<div class="add-ons selected">
<h4>Golf Cover</h4>
<p>Protect against loss or damage up to £1,000</p>
<h4>£6.80</h4>
<input type="button" class="selected-remove" value="Remove " onclick="JavaScript: document.qetForm.NNRS_GLU.value='';updateProductData();" />
This example is one of the extra add ons aviable to the user that has not been selected, If the user was to select this item by clicking {ADD} This would add the price shown in the h4 tags (2.28) to the total price in real time, Same if this was then selected as {Remove} the price would then be deducted.
<input type="hidden" name="NNRS" value="AFFGE" />
</div><div class="bolt-ons">
<h4>Adventure Pack</h4>
<p>Select the Adventure Pack</p>
<h4>£2.28</h4>
<input type="button" class="unselected-add" value="Add " onclick="JavaScript: document.qetForm.NNRS_GLU.value='ABBS';updateProductData();" />
The problem is.. He no longer can support me so i need to change the code to a basic javascript code, I have seen several out their but all these are done by the user inputting values, As you can see my values are already set so i am just not experienced enough the write a script that will add the value to the total price.
could this be done with getelementbyid?
Thanks, And very grateful for any input / advice.

What is the best solution: How to combine 2 buttons in one - may be with js?

I try to make my checkout page more friendly and how to do this:
I have guest form`s and save button after them. And after guest info is saved (instead payment option) are show send my order button - this is from one module Cash on delivery, but instead to choice only this i move button to be showed directly.
BUT: Many clients are confused from this "save" button. I want to marge this two buttons in one.
How to do this? What is the best solution: to add some js when for save button or adding new button instead these 2?
You can see the problem page in my live shop here: http://bijutaniki.com/porychka (do not forget to add product like: http://bijutaniki.com/prysteni/8-prysten-na-nastroenieto.html - and shop is on bulgarian)
Now process looks like that:
What i want to do:
I try two times to add new button with js instead these to but without success. May be if use "save" button and add js to click on other "send order" button will be more easy because when "save" been clicked check fields above and if fields are valid show message.
What are you think, how to combine this buttons.
Thanks!
EDIT:
Save button and message:
{$HOOK_CREATE_ACCOUNT_FORM}
<p class="submit">
<input type="submit" class="exclusive button" name="submitGuestAccount" id="submitGuestAccount" value="{l s='Save'}" />
</p>
<p style="display: none;" id="opc_account_saved">
{l s='Account information saved successfully'}
</p>
<p class="required opc-required" style="clear: both;">
</p>
Send order button (with smile):
<div class="cod_cofirm">
<form action="{$link->getModuleLink('cashondelivery', 'validation', [], true)|escape:'html'}" method="post">
<input type="hidden" name="confirm" value="1" />
<p class="cart_navigation" id="cart_navigation">
<input type="submit" value="{l s='Send order' mod='cashondelivery'}" class="extraorderbutton" />
</p>
</form>
</div>
Because prestashop have controllers may be need to show code from some controller?
I guess there is no valid answer without showing us code, I'll try it anyway:
$('NEW_Send_Order_btn').click(function(e){
e.preventDefault();
$('Save_btn').trigger('click');
if($('Save_btn').hasClass('well_done')){
$('Send_my_order').trigger('click');
}
});

javascript and django

I am converting from PHP to Django and it's proving a real struggle. I want to do an inline edit (a breeze with PHP and Ajax) but I am really, really stuck. Sorry, in advance, for the large amount of code that follows.
I have rendered a 2 divs which contains a number of fields, all the same. One is displayed and the other hidden. When you click on the edit button the div to be updates is dispalyed and the data is in input boxes and a select dropdown so the user cna make changes. The HTML follows"
<div id="display1">
<span style="width:50px;">
<button class="edit" onclick="javascript:toggle('1')">EDIT</button>
</span>
<span>
Blair Leighton
</span>
<span>
Intertrust Private Partners
</span>
<span>
Japan
</span>
<span>
hands off
</span>
<span>
not connected
</span>
<span>
notes
</span>
</div>
<div class="noshow" id="edit1">
<span style="width:100px;"><button class="update" id="1">update</button></span>
<span>
Blair Leighton
</span>
<span style="width:220px;">
<input type="textfield" style="width:210px;" id="new_company" value="Intertrust Private Partners" />
</span>
<span>
<input type="text" id="new_country" value="Japan" />
</span>
<span>
<select id="new_status">
<option value="no contact">no contact</option>
<option value="no contact">hands off</option>
<option value="no contact">ongoing</option>
<option value="no contact">sent email</option>
<option value="no contact">waiting</option>
<option value="no contact">trash</option>
</select>
</span>
<span>
<input type="text" id="new_connection" value="not connected" />
</span>
<span style="width:220px;">
<input type="textfield" style="width:210px;" id="new_notes" value="notes" />
</span>
</div>
There are, in fact, many other divs which have a sequential id display2, edit2 and so on.
Once the edit div is displayed by clicking the toggle button I want to collect the data from each field (in a jquery array) and then pass it to a django view to update the database.
Then, remain on the same page which is refreshed to show the updated values.
How can I do this?
models.py is:
from django.db import models
class recruit(models.Model):
first_name = models.CharField(max_length=25)
last_name = models.CharField(max_length=35)
position = models.CharField(max_length=55)
company = models.CharField(max_length=55)
country = models.CharField(max_length=125)
connection = models.CharField(max_length=55)
status = models.CharField(max_length=55)
phone = models.CharField(max_length=55)
placed = models.CharField(max_length=55)
placed_with = models.CharField(max_length=55)
skype = models.CharField(max_length=55)
notes = models.TextField()
company_url = models.CharField(max_length=125)
All help very gratefully received. Thank you.
Richard
there are django apps which can do the job for you, although i never used them.
quick googling gave me this: http://pypi.python.org/pypi/django-inplaceedit, maybe there are more or even better solutions.
if you really want to code it all by yourselt i'd suggest using a django-ModelForm instead of putting all the fields together manually.
then you can just hook your form-submit with some javascript to make it being submitted with AJAX. i am using jQuery for tasks like this, but any other js library (prototype, dojo, mootools, ...) can do the job too.
in django just safe the data as descibed in the docs for ModelForm and pass it back rendered in the response. onSuccess of your AJAX call update the page with your response text and you are done.
for the views you can also use django's generic update views
you might also be interested in this: https://stackoverflow.com/questions/708801/whats-the-best-edit-in-place-plugin-for-jquery
I can't see how this is any different in Django from PHP. The principles are exactly the same: the JS collects up the data, POSTs it via Ajax, and updates the HTML with the response. The server-side code simply does the saving and returns the result for the Ajax: either as JSON, or as pre-rendered HTML fragments.

Categories