Shopify themes, liquid, logos, and UX
Hi There,
I'm currently switching my shop to the new Dawn theme and my original theme was based on Debut. It seems that the Dawn theme uses an Ajax cart to submit an add to cart action, but I'm unable to add the chosen line item properties. Can anybody help me with the code I need to change, or add to the product-form.js file to achieve this?
Thank you in advance.
Solved! Go to the solution
This is an accepted solution.
Hi,
To add the line in the Dawn theme, you can follow these steps below
1. Go to file sections/main-product.liquid, find <div class="product-form__input product-form__quantity"> and insert the following under that line
<div>
<style>
.product__info-container--sticky {
position: static !important;
}
</style>
<label class="form__label" for="pinfel-select">Pinfel pack</label>
<div class="select" id="pinfel-select">
<select required class="select__select required" id="pinfel">
<option class="fruta" value="Fruta">{{ 'products.product.fruit' | t }}</option>
<option class="jogos" value="Jogos">{{ 'products.product.games' | t }}</option>
<option class="rock" value="Rock">Rock</option>
<option class="espaco" value="Espaço">{{ 'products.product.space' | t }}</option>
</select>
{% render 'icon-caret' %}
</div>
</div>
</div>
2. Go to the file assets/product-form.js, find const body = JSON.stringify({ and add the following code under that line
properties: { Pinfel: $('#pinfel-select select').val() },
Hi @LuckyNigam ,
Thanks for your rapid reply, but I'm looking for a solution that we can share here with others who face the same issue, so if you could post a fix for the Dawn theme to handle line item properties, it would be much appreciated.
Thanks in advance!
Hi,
Could you share your change on the Debut theme? So we can understand your idea closer.
Hi @LamQSolutions ,
Here's the line item property I have added to the product template which works in the old Debut theme, but doesn't work in the new Dawn theme, because the old Debut theme didn't use Ajax and the new Dawn theme has a complete new way of handling the add to cart functionality:
<label class="form__label" for="pinfel-select">Pinfel pack</label>
<div class="select">
<select required class="select__select required" id="pinfel" name="properties[Pinfel]">
<option class="fruta" value="Fruta">{{ 'products.product.fruit' | t }}</option>
<option class="jogos" value="Jogos">{{ 'products.product.games' | t }}</option>
<option class="rock" value="Rock">Rock</option>
<option class="espaco" value="Espaço">{{ 'products.product.space' | t }}</option>
</select>
{% render 'icon-caret' %}
</div>
Thanks in advance!
This is an accepted solution.
Hi,
To add the line in the Dawn theme, you can follow these steps below
1. Go to file sections/main-product.liquid, find <div class="product-form__input product-form__quantity"> and insert the following under that line
<div>
<style>
.product__info-container--sticky {
position: static !important;
}
</style>
<label class="form__label" for="pinfel-select">Pinfel pack</label>
<div class="select" id="pinfel-select">
<select required class="select__select required" id="pinfel">
<option class="fruta" value="Fruta">{{ 'products.product.fruit' | t }}</option>
<option class="jogos" value="Jogos">{{ 'products.product.games' | t }}</option>
<option class="rock" value="Rock">Rock</option>
<option class="espaco" value="Espaço">{{ 'products.product.space' | t }}</option>
</select>
{% render 'icon-caret' %}
</div>
</div>
</div>
2. Go to the file assets/product-form.js, find const body = JSON.stringify({ and add the following code under that line
properties: { Pinfel: $('#pinfel-select select').val() },
Hi @LamQSolutions ,
I had to make a few small adjustments to make it work, but you directed me in the right direction and it works now! Thanks!
Hi @gunnar-1
Glad to hear that the problem was solved! Could you please share your change so it can help other people?
Hi @LamQSolutions ,
Ok, here's my working solution, it's not pretty and I'm sure it could be done better, but it works and hopefully people that need it can adjust it to their needs:
main-product.liquid:
{%- if product.tags contains 'pinfel' -%}
<div class="product-form__input product-form__input--dropdown product-form__pinfel">
<label class="form__label" for="pinfel-select">Pinfel pack</label>
<div class="select" id="pinfel-select">
<select required class="select__select required" id="pinfel" data-type="pinfel-select">
<option class="fruta" value="Fruta">{{ 'products.product.fruit' | t }}</option>
<option class="jogos" value="Jogos">{{ 'products.product.games' | t }}</option>
<option class="rock" value="Rock">Rock</option>
<option class="espaco" value="Espaço">{{ 'products.product.space' | t }}</option>
</select>
{% render 'icon-caret' %}
</div>
</div>
{%- else -%}
<span value="0" data-type="pinfel-select"></span>
{%- endif -%}
product-form.js:
onSubmitHandler(evt) {
evt.preventDefault();
this.itemProperty = document.querySelector('[data-type="pinfel-select"]');
this.cartNotification.setActiveElement(document.activeElement);
const submitButton = this.querySelector('[type="submit"]');
submitButton.setAttribute('disabled', true);
submitButton.classList.add('loading');
const body = JSON.stringify({
properties: { Pinfel: this.itemProperty.value },
...JSON.parse(serializeForm(this.form)),
sections: this.cartNotification.getSectionsToRender().map((section) => section.id),
sections_url: window.location.pathname
});
fetch(`${routes.cart_add_url}`, { ...fetchConfig('javascript'), body })
.then((response) => response.json())
.then((parsedState) => {
this.cartNotification.renderContents(parsedState);
})
.catch((e) => {
console.error(e);
})
.finally(() => {
submitButton.classList.remove('loading');
submitButton.removeAttribute('disabled');
});
}
Thanks for sharing!
This solution works fine but requires an update to product-form.js
Does anyone know how line item properties can be used by theme app extensions? In other words, how can a section on the product page contribute to the line item properties without modifying the theme files?
Thanks!
This is great and very helpful, I was able to add your example to my store with some tweaks using my select options.
Now, does anyone how how to add more than 1 option? I can't get them to both show up in the cart.
I second this.
While I was launching a preorder app, the dawn theme came out, and of course upon testing, the add-to-cart js literately doesn't support lineitem properties in the form.
Which means that any merchant using this theme can not have line-item properties added to their cart forms without customizing a main js asset file. Is this going to be fixed via Shopify, or is it what it is?
What is the reason why adding attributes to the dawn 2.0 theme in this way does not take effect?
It would require one of these pull requests to be merged:
If you're working on a single store, you can amend the theme file global.js with one of these code changes
I found that the answer they gave was to take and modify the global.js file. Can you not modify this file or add attributes, because the original intention of the theme of 2.0 is not to operate on the theme of the customer's store through application extension
If Pull request #391 (or something similar) is to be implemented, would that retroactively update every stores dawn theme, or, will this be a caveat for any merchant who would like to add lineitem properties in their forms going forward?
No idea, sorry. According to the docs (https://help.shopify.com/en/manual/online-store/themes/managing-themes/updating-themes) it might depend on whether there has been changes made to the theme.
So all I had to do in the end was change 1 line in 'product-form.js' and all my line items work great. Even with different line items on different products.
Under const body = JSON.stringify({
Add: properties: { YourNewField: document.getElementById('field').value }
And here is an example of my line items on the product page (just adds a radio button and a text field):
<div class="custom-preferences-box">
<p><strong>Add-On Details</strong> (required)</p>
<label>Is this an add-on for a current subscription?</label><br />
<input required class="required" type="radio" name="properties[Delivery Type]" value="Current Subscription Add-on" data-type="custom-1"> <span>Yes</span>
<input required class="required" type="radio" name="properties[Delivery Type]" value="One-Time" data-type="custom-2"> <span>No, it's a one-time delivery</span>
<br /><br />
<label for="email-address">If YES, please provide the order # or recipients name:</label>
<input id="email-address" type="text" name="properties[Subscriber Info]" data-type="custom-3" class="required grey-input" />
</div>
Full js file:
class ProductForm extends HTMLElement {
constructor() {
super();
this.form = this.querySelector('form');
this.form.addEventListener('submit', this.onSubmitHandler.bind(this));
this.cartNotification = document.querySelector('cart-notification');
}
onSubmitHandler(evt) {
evt.preventDefault();
this.cartNotification.setActiveElement(document.activeElement);
const submitButton = this.querySelector('[type="submit"]');
submitButton.setAttribute('disabled', true);
submitButton.classList.add('loading');
const body = JSON.stringify({
properties: { YourNewField: document.getElementById('field').value }
...JSON.parse(serializeForm(this.form)),
sections: this.cartNotification.getSectionsToRender().map((section) => section.id),
sections_url: window.location.pathname
});
fetch(`${routes.cart_add_url}`, { ...fetchConfig('javascript'), body })
.then((response) => response.json())
.then((parsedState) => {
this.cartNotification.renderContents(parsedState);
})
.catch((e) => {
console.error(e);
})
.finally(() => {
submitButton.classList.remove('loading');
submitButton.removeAttribute('disabled');
});
}
}
customElements.define('product-form', ProductForm);
Hello! Have not been able to get this product-form.js change to work. Is
properties: { YourNewField: document.getElementById('field').value }
literally what we need to add so are those placeholders that we need to fill in for each property we want to add?
If my property is Example, would I add:
properties: { Example: document.getElementById('Example').value }
Thanks for clarifying.
OK, so I was able to get this to work ONE property. For example:
properties: { 'Hardware Color': document.getElementById('hardware-color').value },
However, I need to do this for MULTIPLE properties on the same product and not all products have the same properties.
Also, it appears to work only for the last property on the page. I actually have to remove from the JS file the other properties or add to cart just causes the cursor to spin.
SO, can anyone direct me on how to do this for multiple properties, please?
Adding THIS is not working:
properties: { 'Hardware Color': document.getElementById('hardware-color').value },
properties: { 'Glass Color': document.getElementById('glass-color').value },
properties: { 'Controller Cutout': document.getElementById('fan-cutout').value },
properties: { 'Install Location': document.getElementById('pull-out-enclosure').value },
properties: { 'Free Space Above': document.getElementById('pull-out-vertical-pos').value },
properties: { '_Estimated Ship Date': document.getElementById('estimated-ship-date').value },
User | RANK |
---|---|
187 | |
149 | |
69 | |
46 | |
36 |
Thanks to all Community members that participated in our inaugural 2 week AMA on the new E...
By Jacqui Mar 10, 2023Upskill and stand out with the new Shopify Foundations Certification program
By SarahF_Shopify Mar 6, 2023One of the key components to running a successful online business is having clear and co...
By Ollie Mar 6, 2023