Re: Line item properties in Dawn Theme

Solved

How can I modify product-form.js for line item properties in Dawn Theme?

gunnar-1
Shopify Partner
9 1 6

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.

Accepted Solution (1)
LamQSolutions
Shopify Partner
131 30 44

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() },
Found my answer helpful? Please LIKE or Accept Solutions.
You may be interested in our apps
Scrolly Telling - Create scroll-based animations visually.
Ultimate Sections - Slideshow, Gallery, Collection, FAQs, Brand, Info box, Testimonial and more

View solution in original post

Replies 37 (37)

gunnar-1
Shopify Partner
9 1 6

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!

LamQSolutions
Shopify Partner
131 30 44

Hi,

Could you share your change on the Debut theme? So we can understand your idea closer.

Found my answer helpful? Please LIKE or Accept Solutions.
You may be interested in our apps
Scrolly Telling - Create scroll-based animations visually.
Ultimate Sections - Slideshow, Gallery, Collection, FAQs, Brand, Info box, Testimonial and more
gunnar-1
Shopify Partner
9 1 6

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!

LamQSolutions
Shopify Partner
131 30 44

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() },
Found my answer helpful? Please LIKE or Accept Solutions.
You may be interested in our apps
Scrolly Telling - Create scroll-based animations visually.
Ultimate Sections - Slideshow, Gallery, Collection, FAQs, Brand, Info box, Testimonial and more
gunnar-1
Shopify Partner
9 1 6

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! 

LamQSolutions
Shopify Partner
131 30 44

Hi @gunnar-1 

Glad to hear that the problem was solved! Could you please share your change so it can help other people?

Found my answer helpful? Please LIKE or Accept Solutions.
You may be interested in our apps
Scrolly Telling - Create scroll-based animations visually.
Ultimate Sections - Slideshow, Gallery, Collection, FAQs, Brand, Info box, Testimonial and more
gunnar-1
Shopify Partner
9 1 6

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');
});
}

LamQSolutions
Shopify Partner
131 30 44

Thanks for sharing!

Found my answer helpful? Please LIKE or Accept Solutions.
You may be interested in our apps
Scrolly Telling - Create scroll-based animations visually.
Ultimate Sections - Slideshow, Gallery, Collection, FAQs, Brand, Info box, Testimonial and more
acerill
Shopify Partner
12 1 9

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!

Jesse-James
Shopify Partner
22 0 9

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?

 

Mercantile Apps - simple apps for enterprise growth
Learn more
AEmedia
Shopify Partner
28 0 9

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.

Shopify Partner // Design + Development
YuChen
Tourist
15 0 1

What is the reason why adding attributes to the dawn 2.0 theme in this way does not take effect?

微信截图_20210830161410.png

acerill
Shopify Partner
12 1 9

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

YuChen
Tourist
15 0 1

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

 

Jesse-James
Shopify Partner
22 0 9

@acerill 

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?

 

Mercantile Apps - simple apps for enterprise growth
Learn more
acerill
Shopify Partner
12 1 9

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.

AEmedia
Shopify Partner
28 0 9

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>&nbsp;&nbsp;
  <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);

 

Shopify Partner // Design + Development
AlanAdler
Tourist
10 0 3

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.

 

 

AlanAdler
Tourist
10 0 3

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 },

AlanAdler
Tourist
10 0 3

THIS worked:

properties: {
'Hardware Color' : document.getElementById('hardware-color').value,
'Glass Color' : document.getElementById('glass-color').value,
'Controller Cutout' : document.getElementById('fan-cutout').value,
'Install Location' : document.getElementById('pull-out-enclosure').value,
'Free Space Above' : document.getElementById('pull-out-vertical-pos').value,
'_Estimated Ship Date': document.getElementById('estimated-ship-date').value
},

so long as in the template, I made sure that the element is ALWAYS present.

Some products have SOME of the line item properties but not all, so in the liquid block where I had an IF that controlled whether the property was added, I added an ELSE to add the element as Hidden with no value.

Example:{%- else -%}
<input type="hidden" id="pull-out-vertical-pos" type="text" name="" value="">
{%- endif -%}

 

In other words:

properties: { 'FirstPropName' :  document.getElementById('FirstPropID').value,
'SecondPropName' :  document.getElementById('SecondPropID').value},

PaulNewton
Shopify Partner
7450 655 1558

@AlanAdler wrote:

so long as in the template, I made sure that the element is ALWAYS present.

...


You would be much better of checking if the element exists in javascript an assignining it when  it does.

There's also just more simply serializing any property elements into an object instead of having to create a manual object.

Contact paull.newton+shopifyforum@gmail.com for the solutions you need


Save time & money ,Ask Questions The Smart Way


Problem Solved? ✔Accept and Like solutions to help future merchants

Answers powered by coffee Thank Paul with a Coffee for more answers or donate to eff.org


Aleksej579
Shopify Partner
3 0 0

Thanks for the reply. It works for me too.

 

   const body = JSON.stringify({

     properties: { YourNewField: document.getElementById('testSaveField').value },

     ...JSON.parse(serializeForm(this.form)),

PaulNewton
Shopify Partner
7450 655 1558

@acerill wrote:

It would require one of these pull requests to be merged:

 


That change has been merged  so update your themes https://github.com/Shopify/dawn/pull/509 

Contact paull.newton+shopifyforum@gmail.com for the solutions you need


Save time & money ,Ask Questions The Smart Way


Problem Solved? ✔Accept and Like solutions to help future merchants

Answers powered by coffee Thank Paul with a Coffee for more answers or donate to eff.org


Scott-WebWizard
Shopify Partner
8 0 6

 I used the following and no changes to either product-form.js or global.js files needed

 

 form="product-form-{{ section.id }}"

 

 full example

 

{% if product.type == 'Coffee' %}
<div id="MilkOptions">
<p>
  <strong>Milk Options</strong><br>
  <label><input type="radio" name="properties[Milk Option]" value="Almond" form="product-form-{{ section.id }}"> Almond</label>
  <label><input type="radio" name="properties[Milk Option]" value="Coconut" form="product-form-{{ section.id }}"> Coconut</label>
  <label><input type="radio" name="properties[Milk Option]" value="Macadamia" form="product-form-{{ section.id }}"> Macadamia</label>
  <label><input type="radio" name="properties[Milk Option]" value="Oat" form="product-form-{{ section.id }}"> Oat</label>
  <label><input type="radio" name="properties[Milk Option]" value="Soy" form="product-form-{{ section.id }}"> Soy</label>
</p>
</div>
{% endif %}  

 

Working page

https://shopify-demo.webwizards.nz/products/coffee?variant=40598766813295&fts=0&preview_theme_id=125...

akira2
Visitor
2 0 0

Hello

Can you tell me what I added to make it appear in cart-notification?

ilc
Tourist
3 0 1

Any  notice required isn't working with text input fields?

 

<p class="line-item-property__field">
<label for="childsName">Child's Name:</label>
<input required="required" class="required" id="childsName" type="text" name="properties[Child's Name]" form="product-form-{{ section.id }}">
</p>
AlanAdler
Tourist
10 0 3
See
https://www.w3schools.com/tags/att_input_required.asp

Simply need “required” (no quotes).
akira2
Visitor
2 0 0

Thank you for answering!
I was able to display it on the cart screen by this method.
However, I don't know how to display the properties in the popup window that appears when I add it to the cart. Also, I don't know how to display it in the auto-reply email.
I misunderstood that it could be implemented on the demo site.
I wish I could display the property in an auto-reply email or a pop-up window without editing product.js.

MAPdev
Shopify Partner
16 1 1

@akira2 Is your pop-up cart window using the ajax cart template if so, you need to add the following to your ajax code in side the {{#items}} code in here some where {{/items}} .... if it still does not display you need to find the code in your theme.js that build cart items and add properties    i.e. (var prodName = cartItems.title or var itemQty = cartItems.quantity) etc.. and add var prodProps = cartItems.properties & add to the item object i.e (  item = { key: cartItem.key, url: cartItem.url, properties: prodProps, }    )

 

{{#properties}}
{{#each this}}
{{#if this}}
<span class="ajaxcart__product-meta2">{{@key}}: {{this}}&nbsp;<br></span>
{{/if}}
{{/each}}
{{/properties}}

 

 

lncuster
Tourist
4 0 1

I am using Impulse theme but having the same issue. How do I get line items to work on my theme? 

James_Cirkl
Shopify Partner
14 1 1

@lncuster Could you give a little more context to your issue? Have you tried the above suggestions and they did not work? Can you post some of the code you have tried and where you put i.e. product template, product-form, theme.js etc.. 

littlebundles
Tourist
9 0 3

How do you do this with custom fields, like this clothing embroidery example: https://shopify-demo.webwizards.nz/products/short-sleeve-t-shirt?variant=31619799449711

I have a store where some of my products are able to be customised and the customer would need to enter in a name.

ilc
Tourist
3 0 1
littlebundles
Tourist
9 0 3

this is a great tip! Just installed it and setup a custom field for a product and it works well! thank you so much.

Oupas
Tourist
3 0 0

Thank you @Scott-WebWizard this worked out great! Much simpler and less messy 🙂

 

I was having the same issue as others here: Adding the product to cart didn't work if I had with several forms, and, in case I had different product types/pages that did not require that specific form, I had to include the form code in that page anyway, but hide through css in order to work. With Scott's answer was much simpler and works with all types of forms. My code below for a dropdown menu and a text form:

 

{% if product.type == 'ProductExample' %}
              <div class="product-form__input product-form__input--dropdown">
              <p>
                <label class="form__label">Choose a card</label>
              <select class="select__select" id="Card" name="properties[Card]" form="product-form-{{ section.id }}">
              <option value="Love" >Love</option>
              <option value="Friends">Friendship</option>
              <option value="Blank">Blank</option>
              <option  value="Custom">Custom</option>
              </select>
                </p>
              </div>
              <p class="line-item-property__field ">
                <label class="form__label">Custom Message</label>
                <input class="select__select" id="Message" type="text" name="properties[Message]" form="product-form-{{ section.id }}">
              </p>
{% endif %} 

 

 

adam_mm
Shopify Partner
4 0 4

This is far and away the easiest and safest way to do this.  You can then just drop custom liquid blocks into your templates and away you go.  No mucking around with core files.  Thanks Scott!

Talha_dl112
Visitor
1 0 0

Hi,

I cn't find const body = JSON.stringify({ line in product-form.js  
"2. Go to the file assets/product-form.js, find const body = JSON.stringify({ and add the following code under that line"