How Can I add currency selector on WHMCS custom page? - selector

I am trying to add a currency selector on one of my custom pages where I have displayed the product details.
I want to allow my visitor to change the default currency from this custom page and view the product pricing accordingly.
I have added this code in my custom.tpl
<input type="hidden" name="token" value="{$LANG.go}">
<select name="currency" onchange="submit()" class="form-control">
<option value="">Change Currency (A$ AUD)</option>
{foreach from=$currencies item=listcurr}
<option value="{$listcurr.id}"{if $listcurr.id == $currency.id} selected{/if}>{$listcurr.prefix} {$listcurr.code}</option>
{/foreach}
</select>
</form> ```
But it is not working, every time I select the currency from the dropdown, it refreshes the page. but nothing changes,
please guide what I am doing wrong.
Thanks in advance
Aqsa,

You can do this. You could update your form to either:
Perform a GET request, and add the currency=$id parameter to the URL ($id being the ID for the currency in tblcurrencies.
Or
When your form submits, handle the form input, and set the currency in the session variable:
use WHMCS\Session;
Session::set('currency', $id);
Again, where $id relates to tblcurrencies.id.
Bare in mind that the currency cannot be changed for existing users, and it is not recommended changing their currency after they have made any transactions to avoid accounting/calculation issues.

Related

htmx three dependent selects immediate population of child elements on change

Consider this HTML page using the HTML Javascript package
<html>
<head>
<script src="https://unpkg.com/htmx.org#1.8.0" integrity="sha384-cZuAZ+ZbwkNRnrKi05G/fjBX+azI9DNOkNYysZ0I/X5ZFgsmMiBXgDZof30F5ofc" crossorigin="anonymous"></script>
<title>Test</title>
</head>
<body>
<h1>Prova</h1>
<select name="brand" hx-get="/models" hx-target="#models" hx-trigger="change">
<option value='325i'>325i</option>
<option value='325ix'>325ix</option>
<option value='X5'>X5</option>
</select>
<select name="model" id="models" hx-get="/models2" hx-target="#numbers" hx-trigger="change">
</select>
<select name="number" id="numbers">
</select>
</body>
</html>
Consider that endpoints models and models2 return a bunch of options depending on the value of the select being changed.
The response is something like:
<option value='325i'>325i</option>
<option value='325ix'>325ix</option>
<option value='X5'>X5</option>
I wonder how I can make that whenever I change the select brand, that triggers the HTMX GET Request associated with the model select, which itself will populate the numbers select.
What I see happening, right now, is that the change to the brand dropdown triggers the population of the model dropdown.
I would expect the same to happen for the number dropdown as a consequence of the model dropdown value being changed but that is not happening. Can you elucidate me why that is not happening? And in that case how I can fix that using standard HTMX?
Swapping the new content into the models element does not actually trigger the change event on the models element. You'd need to define an additional trigger event to get the models element to issue its hx-get request when the brand changes and therefore the models options are updated. You could do this purely on the client side in HTMX with a delay so that your models selected value is sent. Or you could have a combination of client custom trigger event and a HX-Response Header sent to the client to trigger that event.
Here is an example of a client event. Added a long 3 second delay to illustrate how the trigger from brand needs to wait until the swap has finished. If you just had the from:brand trigger without delay, it would fire instantaneously (before the models content was populated) so that post would not include the preselected model option. Essentially a race condition. Also went ahead and included the brands element in the models2 request. Maybe you didn't want models2 server side logic have to worry about the brand... but if two different brands had the same model name, then you may not know which set of numbers are supposed to be returned... For the following to work correctly, please add id='brand' to your brand select element.
<select name="model" id="models" hx-get="/models2"
hx-target="#numbers" hx-include="#brand"
hx-trigger="change, change from:#brand delay:3s">
</select>
The other way to do this would be to add a custom event into the model hx-trigger and then trigger that client event from the server in a Response Header. Added a short 5 millisecond delay so that HTMX has time to finish the swap before making the call to models2 .. Again, so that the preselected model is included in the request to models2.
Clientside:
<select name="model" id="models" hx-get="?handler=models2"
hx-target="#numbers" hx-include="#brand"
hx-trigger="change, get-numbers from:body delay:5ms">
</select>
Server Side ASP.NET here (your server may need different syntax for adding Response Header)
Response.Headers.Add("HX-Trigger", "get-numbers");

Country Selector for Shipping Estimation

I am using PS 1.7.6.4. I would like guest shoppers to be able to select their country to get an accurate estimate of their shipping cost. I have put the following code in the /themes/classic/templates/_partials/header.tpl file:
{assign var='countries' value=Carrier::getDeliveredCountries(1, true, true)}
<select class="form-control-select js-country" name="id_country">
{foreach from=$countries item=v}
<option value="{$v.id_country}">{$v.name|escape:'html':'UTF-8'}</option>
{/foreach}
</select>
How do I pass the selection to the cart for shipping calculation?
If you don’t want build your own module and just put the select inside header you have two options:
When user choose one options put it to cookie file and read in cart
OR
Use browser local storage.
Anyway - Inside Cart you have to make an Ajax Request to get info from database OR store your info in Json inside body of cart.
Both will work locally only in user browser, but it’s only estimated.

Why are my Vue/Nuxt Select field states valid by default?

I have a variety of HTML select elements inside of Nuxt.js. I'm also using Vuelidate for validation and this is working as expected. This is a typical select box in my form:
<select
id="location"
name="location"
v-model="form.location"
#blur="$v.form.location.$touch()"
:class="{error: appendErrorClass($v.form.location)}"
>
<option :value="null" hidden>Choose...</option>
<option
v-for="(item, index) in $store.state.quotes.data.practiceStates"
:key="index"
:value="item.data">
{{item.display}}
</option>
</select>
Before selecting any of the options, I'm noticing the following on all select fields.
I've tried removing any Vue magic on a test select field to see if the same results happen.
<select id="location1" name="location1">
<option value="" hidden>Choose...</option>
<option value="one">one</option>
<option value="two">two</option>
<option value="three">three</option>
</select>
Still seeing valid: true. Is there anything I'm overlooking that would cause the validity to default to true? Thanks in advance for any help or guidance on this issue.
UPDATE For Clarification:
Vuelidate validation works just fine. The issue I'm dealing with is the select field property Validity.validate. I only mention Vuelidate to give full context.
HTML Select is a sort of "strange" form element in that validity is typically checking to see if there's a readable value. Since a select always has something picked, it validates...
This is different from say a telephone input that has a specific pattern required to be valid.
I haven't used Vuelidate specifically, but I read the docs as saying, if you left the v-model="form.location" there's a good chance it's simply validating that a value exists so Any selcted item would qualify.
In my original post, I referenced the dynamic style based on the vuelidate library: :class="{error: appendErrorClass($v.form.location)}"
#PierreSaid responded to this post and later deleted his/her reply. Turns out, his response was helpful in pointing me to some Vuelidate attributes that were able to assist in a workaround for my issue. Thank you, PierreSaid.
I have since updated that dynamic class to be a mixin that looks like this:
export default {
methods: {
appendErrorAndValidityClass(field) {
return {
error: field.$error,
invalid: field.$invalid,
};
}
}
};
After importing the mixin into the Vue partial, my select box looks like this:
<select
id="location"
name="location"
v-model="form.location"
#blur="$v.form.location.$touch()"
:class="appendErrorAndValidityClass($v.form.location)"
>
This appends a class of invalid when the select field has not been updated. It also updates the error style accordingly. Now, I can assign styles for when the select field has an invalid class. This solves the overall issue for me. Thanks for your help PierreSaid and Bryce.

DOJO: How to validate (required="true") selectOneMenu

How i can validate DOJO selectOneMenu (required="true") here is some dummy code.
<select required="true" missingMessage="Ooops! You forgot your gender!"
name="gender" id="gender" data-dojo-type="dijit/form/?">
<option disabled="true" value="">Select a Gender</option>
<option value="1">Male</option>
<option value="2">Female</option>
</select>
Dojo provide 3 type of combobox :
Select
It is simple combobox like select in HTML with no validation and not provide any search facility inside select options.
ComboBox
It is pure form of combobox and name as ComboBox again it will not provide any default validation but it provide search facility within its options.
FilteringSelect
It is an advance form of select have default facility of validation and search facility. And it also has property to take value as input tag take value in HTML.
In dojo you can also try custom validation which is provided inside dojox library.
I hope it will help you.

Can a user-sorting system for a collection be done in Shopify?

In Shopify, a collection can have a default sorting order, which is great. But is there a way to change the default sorting order prior to rendering the collection's list of products? What I'm trying to accomplish is to put a "sort by" dropdown menu on the page, allowing the customer to sort the current list by price, by brand, by best selling items, alphabetically, etc. like so many modern shopping carts out there.
Collections are sorted ahead of time rather than sorted dynamically so that pages can load faster.
You can create multiple collections with the same products, but with different sorting. Then you can navigate to relevant collection based on user input.
There is an app for this now:
https://apps.shopify.com/power-tools-sort-selector
*disclaimer - I'm the developer :)
We've recently added the ability to sort your collection dynamically on the storefront (before you could only sort a collection by one order in the backend.
docs:
http://docs.shopify.com/manual/configuration/store-customization/advanced-navigation/add-a-reorder-drop-down-menu-to-a-collection-page
ex code:
https://gist.github.com/carolineschnapp/11352987
If you want to avoid paying for the app - which may or may not duplicate each collection by the number of selections required - use / adapt the code below:
<script>
// jquery is already running on the site, so we use it to check the document is ready
$(document).ready(function() {
// Identify a Select Option from the value in the URL query text
// Where this exists as an Option Value, add the 'selected' attribute to the Option
// This ensures that when the page reloads the current option will be showing
$("#selectSort option[value='{{collection.sort_by}}']").attr('selected', true);
});
</script>
<div>
<!--
The Select Tag watches for a change, then pushes a new window.location using the value
of the Option selected by the user
-->
<select id="selectSort" onchange='window.location="{{ collection.url }}?sort_by=" + this.value'>
<option value="price-ascending">Price (lowest first)</option>
<option value="price-descending">Price (Highest first)</option>
<option value="title-ascending">A-Z</option>
<option value="title-descending">Z-A</option>
<option value="created-descending">Latest Addition</option>
<option value="best-selling">Most Popular</option>
</select>
</div>