How do I add a metafield to liquid in Shopify? - shopify

I'm trying to edit a section in my Shopify theme which displays a video. I'm using the section on product pages and the URL for the video is inserted by using the theme editor tool. As such the same video inserted will show on every product page using that template. However, I would like to use a different video on each product page. I can't see a way to do this through the theme editor unless I duplicate the template for each and every product that needs its own video URL (seems a bit overkill).
I found this code which controls the video section, and the bit I'm trying to figure out is how I can change the 'assign video_id' to use a metafield so that I can add this per product by simply adding the video URL on a specific product page. I can't think of an easier way to achieve what I need, but thought changing a metafield for each product that needs a custom video URL would be the best way to do it, working possibly similar to this:
{% if template.name == 'product' %}
{% if product.metafields.my_fields.product_video_url %}
{{ product.metafields.my_fields.product_video_url }}
{% endif %}
{% endif %}
If anyone had an idea of how I can do this using the code below and inserting a metafield (and even better, a metafield IF it's filled, otherwise default back to video_url.id) I would really appreciate it.
{%- liquid
assign bg_color = section.settings.background-color
assign button_text = section.settings.button-text | escape | truncate: 30
assign button_url = section.settings.button-url | url_escape
assign full_width = section.settings.full-width
assign heading = section.settings.heading | escape
assign darken_video = section.settings.darken-video
assign light_text = section.settings.light-text
assign section_height = section.settings.section-height
assign sub_heading = section.settings.sub-heading | escape
assign thumbnail = section.settings.image
assign video_url = section.settings.video-url
if video_url.id
assign video_id = video_url.id
else
assign video_id = '_9VUPq3SxOc'
endif
assign cover_link = false
if button_text == blank and button_url != blank
assign cover_link = true
endif
assign button_type = 'button'
if light_text
assign button_type = 'inverted-secondary-button'
endif
-%}
Thank you for any help at all.

Metafields are pretty simple, and very useful. First off, you can set them in the Admin. Create one with a description.
Note the concept of my_fields is really dumb, instead, think of it as "context", the "what am I in all this". So you might use a namespace here, like "product_videos". Hence, at this point, think of it as a box named, with whatever is inside the box, still a mystery!
product.metafields.product_videos
Or your company name. Or your cat's name. Or whatever turns your crank. my_fields is just generic filler. Means nothing.
Once you get over that hump, that you've now got a namespace, you can actually get down to the nitty-gritty. Anything of value to you is likely to be a string here, a string representing a video. So you want to make the type of the Metafield to be text. A string of text.
To be of much use, you need a key. You want to grab onto the key! So if a product has a special movie, let the key guide you right to it! The key is going to be something brilliant like; video_id! So now you have a product, with a Metafield resource, in your namespace, product_videos, with a key! Namely video_id. And you can then go to that product in your Shopify Admin, and at the bottom of the details page, fill in the answer to the question of video_id. Give it some info. Where to find the video. What it is called. Anything useful to you.
Now in your theme, just reference {{ product.metafields.product_videos.video_id }} when you need it.

Related

Liquid - Load all products from collection handler not working

I am trying to load all products by the given handler from a collection.
They will click on a box (each box is a different collection), then it should load all products for that collection.
My issue is that my assigned variable cannot read the input from javascript.
I am doing onclick(id, name, handle) where i catch the handle and pass it to the liquid.
My code is:
function loadProducts(collectionH) {
var html = '';
var handlerString = collectionH;
console.log('Loading products...');
{{collectionHandleNew}} = handlerString;
console.log({{collectionHandleNew}}); // log the handler
// Make sure the current product name is loaded
{% if collectionHandleNew -%}
{% if selectedCategory -%}
console.log('Collection handle is set: ' + {{collectionHandleNew}});
{%- for product in collections[collectionHandleNew].products -%}
console.log({{product.id}});
{%- endfor -%}
{% else -%}
console.log('Selected category not found');
{% endif -%}
{% else -%}
console.log('Collection handle is not available');
{% endif -%}
return html;
}
The console is showing this:
view the image
The trick here is to remember that Liquid and Javascript serve two completely different purposes:
Liquid is a templating language that is parsed server-side to generate the documents that are sent to the client's browser, and is never seen by the client.
Javascript is a programming language that is parsed client-side to do dynamic things on the page and is never executed on the server.
Why is this distinction important? Because it means that we can use Liquid to generate Javascript, but the reverse is never true. It also means that any variables that we pass from Liquid to Javascript will only be current as of the time the document is generated and cannot be affected by anything that happens on the page once it's been rendered!
If your code needs to fetch a collection dynamically, I would recommend creating a function that takes a collection handle and loads the products entirely through Javascript using your favourite tool (fetch, jQuery.getJSON, XMLHttpRequest, Axios, etc).
To fetch products from a collection from the storefront, you can use /collections/<some-collection-handle>/products.json (for example, /collections/drawstring-bag-hoodies/products.json). If you're feeling fancy, you might also consider looking into the storefront GraphQL API instead of the traditional REST API.
One final note: Whenever you are dumping variables from Liquid into Javascript, I strongly recommend using the | json Liquid filter to ensure that the resulting output is Javascript-legal. There are lots of ways a Liquid variable dump can break Javascript, such as when the variable is unexpectedly empty, when it contains ' or ", when it contains line breaks, etc. By running the Liquid variable through this filter, the resulting output will be wrapped in the appropriate brackets or quotes, all special characters within will be properly escaped, and empty values will print null.

How To Enable Block Inside Fifty Different Sections Without Copying Meta Code?

I am developing a Shopify Theme. The structure I have now is (excerpt):
Snippets
custom-message-snippet
Sections
custom-message-section
welcome-page-a-section
welcome-page-b-section
Templates
welcome-page-a-template
welcome-page-b-template
...
Custom message snippet uses settings that are in the custom-message-section, that is:
a) message
b) header text
I'd like for users to be able to add custom-message-snippet to welcome-page-a and welcome-page-b in a way that settings for both are different.
I can not render section 'custom-message-section" inside welcome pages because it is not possible (and a workaround is nasty).
There are fifty welcome pages. Every welcome page is totally different.
My question is:
How to allow users to use custom-message-snippet in all welcome pages without copying and pasting custom-message-page setting schema to each and every welcome page?
combine custom-message-section to custom-message-snippet
combine welcome-page-\w+-template to welcome-page-template, you only need to have one template and schema set, the user will control the sections in schema selection.
in template, use schema to select the page-content; this, defined by a bunch of if-else /switch statement.
{% section "welcome-page-custom-message-section" %}
{% section "welcome-page-content" %}
in welcome-page-custom-message-section
{% render "custom-message-snippet" with "string from welcome-page-section schema " %}
create checkbox select schema for custom message to appear or not.
Short: You can't.
Long: Using storefront 2.0, you end you having blocks, which can be added manually to any template.
It is possible if you have a little knowledge of Node.js and you're using the Shopify CLI.
Check the solution here: Shopify Section / Block Schema In A Separate File. It is possible 

In Shopify, am i able to change the display of variants title?

my variants title is “pack/4 bottles:4/PK”
“4/PK” is needed for shipping company to catch specific item.
However, it looks ugly when "4/PK" is displayed on page
Is there a way to hide it? Which liquid template should i touch?
Should I use
{{variant.title|move:'4/PK'}}
where should i put this code?
While this sounds more like something that should be assigned as an option for your variants instead of in the title, you can hide the part of the variants title that you don't want via using split and first
https://help.shopify.com/themes/liquid/filters/string-filters#split
split can be used to split a string (in this case your variant.title) into an array based on a set delimiter to divide it.
So you could do something only the lines of
{{variant.title | split: ':' | first }}
In your case, the output of the above would be: pack/4 bottles.
As for which liquid templates you will need to edit this into ... it will depend on your store. However some common areas would be:
product.liquid
cart.liquid
I highly recommend you read the the shopify liquid documents Here
Also, make sure to make a backup theme before doing any liquid changes in your theme that you are unsure of.
Hope this helps!

multiplication in django template without using manually created template tag

I want to achieve multiplication operation in django template. For example
I have the values,
price=10.50
quantity=3
With the help of this link
http://slacy.com/blog/2010/07/using-djangos-widthratio-template-tag-for-multiplication-division/
i tried below codes for achieving it,
{% widthratio quantity 1 price %}
but its returning only 31. But i need the answer in float (31.5)
And i want to achieve it without using the manually created tags
How can i achieve it?
Thanks in advance...
You can use the built-in widthratio template tag.
a*b use {% widthratio a 1 b %}
a/b use {% widthratio a b 1 %}
Note: the results are rounded to an integer before returning.
#see https://docs.djangoproject.com/en/dev/ref/templates/builtins/
There are 2 approaches:
Computing the values inside the view and pass them to the template (recommended in my opinion)
Using template filters
In the manner of the add filter, you could always create your own multiply filter, creating your own custom filter:
from django import template
register = template.Library()
#register.filter
def multiply(value, arg):
return value * arg
Then in your template, something like that should work.
{{ quantity | multiply:price }}
This is not tested, and I never did this as - again - I find neater to compute datas inside the views and render only with the templates.
Another approach that I have used seems cleaner to me. If you are going through a queryset, it doesn't make sense to compute the values in your view. Instead, add the calculation as a function in your model!
Let's say your model looks like this:
Class LineItem:
product = models.ForeignKey(Product)
quantity = models.IntegerField()
price = models.DecimalField(decimal_places=2)
Simply add the following to the model:
def line_total(self):
return self.quantity * self.price
Now you can simply treat line_total as if it were a field in the record:
{{ line_item.line_total }}
This allows the line_total value to be used anywhere, either in templates or views, and ensures that it is always consistent, without taking up space in the database.
I know it's been so long since this question came out but, now there's a library called django-mathfilters which made mathematical operations easier in Django templates. you can easily write
<li>42 * 0.5 = {{ answer|mul:0.5 }}</li> for multiplication.
check it out https://pypi.org/project/django-mathfilters/
Multiplication with variable in Django.
1st: install & then register "mathfilters" at INSTALLED_APPS in setting.py
2nd: Add {% load mathfilters %} in html Page
3rd: Multiply with variable like{{response.notSatisfied|mul:100}}

Did liquid array accessors in shopify templates change recently?

For some reason this bit of liquid just stopped working in a site I did some months back:
{% assign packs = collections.packs.all_products %}
{{ packs[0].title }}
Accessing the array items in a for loop still works, but I am unable to access the items directly using an index value. Is this a recent change to the template system or is something else going on?
this should work again. A change in liquid that caused this was reverted last week.