要访问购物车中产品对象中的元字段(来自Accentuate Custom Fields中的自定义字段)?

时间:2018-09-07 19:28:33

标签: javascript shopify cart

我在Shopify项目中使用Accentuate Custom FieldsCart.js。我已经通过ACF在我的产品中添加了一些自定义字段。这些字段通过product.metafields.accentuate.[key]出现在产品对象上。

我正在使用Cart.js定制我的购物车体验,希望能够从购物车中的ACF中访问某些值。

我尝试通过在购物车布局中添加以下内容(每个项目都是JS循环中产品的名称)来访问此自定义字段:item.metafields.accentuate.product_benefits_content

但是,我遇到以下错误:Uncaught TypeError: Cannot read property 'accentuate' of undefined

我还尝试了:根据我在Stack Overflow上找到的响应,item.product.metafields.accentuate.product_benefits_content

这会给出一个稍微不同的错误:Uncaught TypeError: Cannot read property 'metafields' of undefined

要访问购物车中的这些自定义字段,我需要做什么?

这是我的控制台中产品对象的屏幕截图:

The product object

2 个答案:

答案 0 :(得分:2)

您所困扰的不仅仅是两个问题。当您谈到item.metafields时,这就是Liquid。不是Javascript。如果要使用购物车中的元字段的内容,则可能需要将Liquid的元字段呈现为某些基于JS的数据结构。

我要这样做的方法(现在可以使用10年以上)是在模板的Liquid渲染阶段中,将感兴趣的项目的元字段存储在键入变量ID(或产品ID,如果适用的话)的内容中)。然后在JS世界中,一旦DOM呈现完毕,就运行一个函数来遍历您的ID,并根据需要显示/隐藏额外的数据。确实与创建元字段或使用cartJS无关,而是更为通用。如果情况良好,则可以在cartJS中入侵事件监听器,以显示/隐藏您的额外数据,例如在工具提示中或类似内容中显示。

答案 1 :(得分:1)

在Shopify上,元字段是半保护的,不属于常规产品输出。您可以使用产品页面上的简单脚本自己对此进行测试:

<script>
  var product_info_from_liquid = {{ product | json }}
  console.log('Product info from Liquid:',product_info_from_liquid)
</script>

请注意,无论产品是否具有元字段,以上内容都不会输出元字段。

同样,如果您从两个前端产品端点中加载产品的关联JSON对象,则会省略元字段。为了进行验证,我们可以通过从Shopify的两个前端端点获取JSON输出来进行测试:

<script>
  //Grabbing the data for the 'sleepy-head' product from the .js endpoint
  jQuery.ajax({
    url:'/products/sleepy-head.js',
    dataType:'json',
    success:function(product){
      console.log('The ".js" results:', product)
    }

  //Grabbing the data for the 'sleepy-head' product from the .json endpoint
  //I don't know why Shopify serves different at the .js and .json addresses, but apparently they do
  jQuery.ajax({
    url:'/products/sleepy-head.json',
    dataType:'json',
    success:function(product){
      console.log('The ".json" results:', product)
    }

  })

</script>

同样,我们注意到,无论我们尝试以哪种方式获取信息,我们的请求都不会提供任何元数据。

这使我们有了一个令人沮丧的认识:元字段只能通过Liquid访问

那我们该怎么办?

Metafields是半保护的:您必须知道一个名称空间存在,并且可以在Liquid中访问它。我认为,这在某种程度上是为依赖元字段来完成其工作的应用程序提供一层保护。 (例如,如果知道Shopify运作方式的潜在客户打开一个窗口,该窗口显示一些应用程序的元数据有关获得更高价格的资格,那将不是很好。)

一种方法,我们需要创建新的变量来存储所需的元数据,然后在JS循环中使用该变量。

我们有几种选择供您选择,哪种选择取决于您。这里有两个想法:

想法1:在页面上创建全局变量

这通常是最简单的,但是创建许多全局变量可以认为是草率的。另外,Liquid仅在页面加载时呈现,因此,如果您的网站非常动态,您可能会发现客户的行为可能导致您没有加载所有元数据的情况。

为此,我们将在Javascript中创建一个对象,该对象使用我们可能关心的页面上每个产品的唯一标识符-最明显的选择是产品的ID或产品的句柄,因为这两个选择保证是唯一的。

由于我们仅保存有问题的应用程序/功能的元数据,而不是保存产品中可能存在的每个元字段,因此我们创建一个名为save-accentuate-metadata.liquid的代码段来保存逻辑:

<script>
  // Initialize our global object only if it doesn't exist yet
  window.AccentuateLookup = window.AccentuateLookup || {}
  AccentuateLookup[{{ product.handle | json }}] = {{ product.metafields.accentuate | json }} 
</script>

现在,我们只需要在有产品对象的所有地方都包括它-产品页面,集合产品循环等即可。我们期望代码段中有一个名为product的变量,所以让我们来了解一下在我们的摘要调用中:

 {% include 'save-accentuate-metadata', product: product %}

如果我们的代码有可能需要在搜索页面上运行,那么include将需要引用在搜索页面上调用的变量(通常为result):

 {% if result.object_type == 'product' %}
   {% include 'save-accentuate-metadata', product: result %}
 {% endif %}

最后,我们要确保我们保存了购物车中当前商品的所有元字段数据。我们会将调用放置在全局位置,例如layout / theme.liquid(或包含在theme.liquid中的代码段)

{% for item in cart.items %}
  {% include 'save-accentuate-metadata', product: item.product %}
{% endfor %}

现在,我们已经保存了所有这些信息,只要我们具有产品句柄,就可以使用所需的任何脚本来访问它。

// Meanwhile, in some other script on the page:
if(typeof AccentuateLookup === 'undefined'){
  console.error('No data initialized!')
}
var accentuate_data = AccentuateLookup[item.handle]
console.log('Our records show the following for' + item.title, accentuate_data)

想法2:创建我们自己的自定义终结点

这需要花费更多的时间,但是它为您提供了自己的终结点,您可以随时按此终结点来获取所需的数据。这样一来,您就可以更好地响应网站上运行的精美功能或应用程序,这些功能或应用程序可以操纵购物车或加载最初不在页面上的产品(例如追加销售风格的应用程序)。请注意,按照此路线进行操作将意味着您需要进行异步AJAX调用来获取数据,这可能会在加载数据时产生延迟。

要创建自定义端点,我们首先为要从中获取数据的对象类型创建一个新模板。让我们做两个:一个用于购物车,它将提供我们购物车项目的所有数据,另一个用于单个产品。

让我们首先创建一个名为cart.accentuate.json.liquid的模板,其中包含以下内容:

{% layout none %} {% comment %} That tells Shopify to ignore all the layout code/HTML, freeing us to create a simple JSON object {% endcomment %}
{
  {% for item in cart.items %}
    {% comment %}Output the JSON data, and append a comma unless we're on the last one{% endcomment %}
    {{ item.handle | json }}: {{ item.product.metafields.accentuate | json }}{% unless forloop.last %},{% endunless %}
  {% endfor %}
}

以防万一我们只想获取一种产品,让我们为product.accentuate.json.liquid创建一个模板。由于我们要获取特定产品,因此除元数据外,我们可能不需要其他任何东西:

{% layout none %}
{{ product.metafields.accentuate | json }}

现在,通过在查询字符串中指定与模板后缀匹配的view,我们可以使用AJAX调用从任意代码中访问这两个代码。例如:

jQuery.ajax({
  url:'/cart?view=accentuate.json',
  success:function(unparsed_json){
    var cart_data = JSON.parse(unparsed_json)
    console.log('This just in from cart.accentuate.json:', cart_data)
  }
})

var handle = 'sleepy-head'
jQuery.ajax({
  url:'/products/' + handle + '?view=accentuate.json',
  success:function(unparsed_json){
    var cart_data = JSON.parse(unparsed_json)
    console.log('This just in from product.accentuate.json:', cart_data)
  }
})

请注意,当我们以这种方式创建自定义终结点时,Shopify将像常规HTML页面一样提供其响应。如果我们尝试指定期望JSON响应,则这可能导致jQuery的AJAX函数行为异常。发现所有意外行为都留给读者作为练习,但总的来说,您希望像正常的HTML页面一样获取页面,然后使用JSON.parse将检索到的文本转换为正确的JSON。对象。

我希望这可以帮助您完成正在使用的功能!


免责声明:上面的所有代码都是徒劳的,尚未经过打字错误测试。如果无法立即解决任何问题,请评论,编辑和/或检查任何明显的不良代码语法