How to make BigCommerce Category Description accessible to display within navigation - bigcommerce

I am building a custom navigation for a BigCommerce site and need to display category descriptions within the navigation items in addition to name and url.
My navigation is being displayed via a component so I know I can't request Front Matter there, but as name and url are already accessible I thought the description would be as well..
Here is part of my navigation code where i'm trying to display the data. Any tips on how to achieve this would be appreciated!
{{#each children}}
<li class="navigation__submenu-item">
<a class="navigation__submenu-action has-subMenu"
href="{{url}}"
>
{{#if image}}
<img class="navigation__submenu-img" src="{{getImage image}}" alt="{{image.alt}}" />
{{/if}}
<div>{{name}}</div>
<small class="navigation__submenu-msg">{{description}}</small>
</a>
</li>
{{/each}}

You do indeed need to specify to show the description with Front Matter. Something that is not explained well in the BC documentation is that you can actually specify global Front Matter in the config.json file. Assuming you are developing local with the Stencil CLI, you can edit the config.json file. You will look for the "resources" object and append the following code to it:
"categories": {
"description": true
}
So, if your resources object looks like this (default Cornerstone):
"resources": {
"cart": false,
"bulk_discount_rates": false,
"shop_by_brand": {
"limit": 10
}
},
Change it to this:
"resources": {
"cart": false,
"bulk_discount_rates": false,
"shop_by_brand": {
"limit": 10
},
"categories": {
"description": true
}
},

Related

How to display data from Vuex store in life time in Vue

I want o show data from Vues store. So first I want to check if authentication true, if it is, I want to show data from Vuex. Here is my shortcode:
<li v-if="authenticated">
Hello, {{ getUser.attributes.first_name }}
</li>
computed: {
getUser() {
console.log(this.$store.state.user)
return this.$store.state.user;
}
},
But I am getting error like you see in the picture below, why do you think it might be? Why first the object is coming empty and then object is filled?
Add a condition to the v-if directive because at the first rendering the attributes property is not available :
<li v-if="authenticated && getUser.attributes">
Hello, {{ getUser.attributes.first_name }}
</li>

Nuxt, Strapi can't get media url

Could you guys please check my code and help me out.
I've uploaded some media to strapi and assigned them to each drink. Now I want to access that data with axios, I can get id, description, title etc. but I can not get URL from media.
Anyone could help please. Thanks!
NUXT:
<v-img
:src="'url(${http://localhost:1337}/drink.media.url)'"
></v-img>
<script>
async created() {
try {
const response = await axios.get("http://localhost:1337/drinks");
this.drinks = response.data;
} catch (error) {
this.error = error;
}
console.log(this.drinks)
},
};
</script>
JSON FROM POSTMAN
[
{
"id": 2,
"title": "Coca-Cola",
"description": null,
"price": 1,
"published_at": "2021-10-16T19:02:52.099Z",
"created_at": "2021-10-16T19:01:26.228Z",
"updated_at": "2021-10-16T19:02:52.124Z",
"unit": 250,
"media": [
"hash": "coca_cola_original_282x130_8baa6d1d20",
"ext": ".webp",
"mime": "image/webp",
"size": 37.01,
"url": "/uploads/coca_cola_original_282x130_8baa6d1d20.webp",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"created_at": "2021-10-16T18:56:02.187Z",
"updated_at": "2021-10-16T18:56:02.206Z"
}
]
},
Thanks!
I don't know how you upload your images in strapi, but below I describe my method for uploading images of book covers in my strapi local-host and the way I access the image in my nuxt app. Maybe it is helpful for you to use it in your app.
First I made a new media field in my strapi "content-types builder" section and named it "bookCover". after that I upload my image in database for each book.
Second I used fetch() instead of created hook in my Nuxt app. below is the code of my Nuxt page script:
data() {
return {
books: [],
}
},
async fetch() {
this.books = await this.$axios.$get('http://localhost:1337/books');
}
Finally according to Nuxt documentation I used this code in my template part of my page:
<div>
<p v-if="$fetchState.pending">Fetching mountains...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<!-- you must enter your index of drinks, for example here I access the first book image -->
<v-img max-width="250" :src="`http://localhost:1337${this.books[0].bookCover.url}`"></v-img>
</div>
</div>
I think if you use this method and use "fetch" hook and also modify the way you call src attribute in "v-img", you can access your image. Also notice that my variable names are different from your names and you must change them.

Vue CLI clickable dynamic url from a news API

I'm fetching data from newsapi.org and I want there to be a clickable link after the headlines so that you can read more about the article. But I can't make it work.
Maybe this is too advanced for me since I'm no good at coding. I thought maybe there was a simple way of making the dynamic urls work.
<template>
<div class="api">
<h1>Latest gossip</h1>
<br />
<div v-for="item of items" v-bind:key="item.id">
<h3>{{ item.title }}</h3>
<p>{{ item.description }}</p>
<a v-bind:href="adress">
{{ item.url }}
</a>
</div>
</div>
</template>
I use axios.
<script>
import axios from "axios";
export default {
name: "Api",
props: ["articles"],
data() {
return {
items: [],
adress: "item.url"
};
},
mounted() {
this.getInfo();
},
methods: {
getInfo() {
axios({
method: "GET",
url:
"https://cors-anywhere.herokuapp.com/https://newsapi.org/v2/top-headlines?country=se&category=entertainment&apiKey=XXX",
dataType: "json",
headers: {
"X-Requested-With": "XMLHttpRequest",
"Access-Control-Allow-Origin": "*"
}
}).then(res => {
/* eslint-disable no-console */
console.log(res.data);
this.items = res.data.articles;
});
}
}
};
</script>
You can use vue-router in that case. You create a route with a parameter /news/:id in router/index.js eg.
const router = new VueRouter({
routes: [
{ path: '/news/:id', component: SingleNews }
]
})
then instead of
<a href=""/></a>
use
<router-link :to="{ name: 'news', params: { id: news.id }">{{news.headline}}</router-link>
And finally, retrieve parameter in a SingleNews.vue component using
this.$route.params.id
You can read more about vue-router and dynamic routes in the documentation https://router.vuejs.org/
So from what I understand, you're going to have a separate url for each different news article. It seems like there is a slight misunderstanding about how that information will be passed into the anchor tag, where it should be coming from, and how you're using data.
First, let's address your data method. If you look at the structure of your data you can see that you have an items property, which is an array and an adress property, which is set to a string.
data() {
return {
items: [],
adress: "item.url"
};
},
The problem here is that adress is not dynamic. It will always be the literal string "item.url", which is to say that it will always represent those characters ("item.url") in that order, but it doesn't actually represent any specific item's url property.
The good news is that you should already be seeing the correct url displayed on your page here:
<a v-bind:href="adress">
{{ item.url }}
</a>
Remember that an anchor tag in this case has two parts:
1. What we're displaying to the user.
2. Where we're telling the browser to redirect to.
The proper syntax here (without Vue) would be something like:
<a href="https://somelinktogoto.com">
Some text to display
</a>
What you're currently saying is: "I want an anchor tag to display the item's url to the user and redirect to whatever is stored in the data property called adress". Since adress is only storing the string "item.url", if you inspect your html that's been generated in your browser, I would suspect that all of your anchor tags look something like this:
<a href="item.url">
https://somenewsarticle.com
</a>
Luckily, the fix here is simple. Since you're already using v-bind, the href can use dynamic information, or information that's stored in your data somewhere, which can be referenced by its name. Then you can choose to display anything you'd like to your user. You can also delete your adress property from data, because it's not serving any purpose if all the urls are contained within items.
Try:
<a v-bind:href="item.url" target="_blank">
Read more...
</a>
data() {
return {
items: [],
}
}
Also, no one is good at coding at first, just keep trying to understand how data is flowing and you'll get there!
This line worked out great! Thank you!
<a v-bind:href="item.url" target="_blank">Read more here: </a>
I also deleted the adress data.

Rendering data in Vue

I'm trying to create a Card component in Vue that renders some data I pull from firebase. In React I'd pretty much just use map and render out a <Card /> component then go create the Card component separately. Something like this
anArray.map((item, index) => return <Card key={index} index={index} item={item}/>
That would give me the specific item and I could work off the data from there. I'm not sure how to accomplish the same type of thing in Vue. I've created a JSFiddle. The data and bootstrap is already pulled in. I store the data in an object. Is storing it in an object or an array preferred?
https://jsfiddle.net/agzLz554/
The data should be an array because you actually need render item list. If you store it in object, you need to extract key/value mapping, and flatten to array. Because you question actually has nothing to do with the parse, so i set the data directly into vue data.
There are 4 problems:
you should store data in array, not object
you should not set template attribute in vue instance, it's used for component, not the root instance
your card html code should live inside in #app, otherwise, it can't be recognize
your card code loop, should not set id='card', id should be unique
check this JSFiddle example, https://jsfiddle.net/seaify/najm1uer/
<script src="https://unpkg.com/vue#2.0.3/dist/vue.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.4.1/firebase.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css" integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
<div id="app">
<div class="card" v-for="resource in resources">
<div class="card-header">
<!-- Author Name -->
</div>
<div class="card-block">
<h4 class="card-title">{{resource.title]}}<!-- Article Title --></h4>
<p class="card-text">{{resource.desc}}<!-- Article Description --></p>
Go somewhere
</div>
</div>
</div>
/**
* Created by chuck on 2/11/16.
*/
var vm = new Vue({
el: '#app',
data () {
return {
resources: [
{
"objectId": "-KVSES7sKx-kk31gPyiz",
"authorId": "3F14Sh3vCMXhRfZyxRPBPzn8Rdf2",
"authorImage": "https://lh3.googleusercontent.com/-5QsKgD8Li8k/AAAAAAAAAAI/AAAAAAAABbY/v-uLFhw6k8Q/photo.jpg",
"authorName": "Maxwell Gover",
"desc": "Other developers actually have to use the APIs you design. So don’t let those APIs suck.",
"quiz": [
{
"options": [
{
"isAnswer": true,
"text": "True"
},
{
"isAnswer": false,
"text": "False"
}
],
"text": "The more dependencies you have, the more potential problems it can cause in downstream consumer code"
},
{
"options": [
{
"isAnswer": true,
"text": "True"
},
{
"isAnswer": false,
"text": "False"
}
],
"text": "You should try to keep your code as self contained as possible."
}
],
"timesPassed": 0,
"title": "How to design APIs that don't suck",
"type": "article",
"url": "https://medium.freecodecamp.com/https-medium-com-anupcowkur-how-to-design-apis-that-dont-suck-922d864365c9#.my0qpwrp5"
},
{
"objectId": "-KVSXfEragBTcqcyMTAR",
"authorId": "3F14Sh3vCMXhRfZyxRPBPzn8Rdf2",
"authorImage": "https://lh3.googleusercontent.com/-5QsKgD8Li8k/AAAAAAAAAAI/AAAAAAAABbY/v-uLFhw6k8Q/photo.jpg",
"authorName": "Maxwell Gover",
"desc": "How to prioritize improving user experience",
"quiz": [
{
"options": [
{
"isAnswer": true,
"text": "True "
},
{
"isAnswer": false,
"text": "False"
}
],
"text": "No matter how clever a design is, it is rendered useless if it fails to be understood."
}
],
"timesPassed": 0,
"title": "7 Tips to Improve Your UX Strategy",
"type": "article",
"url": "https://uxdesign.cc/7-tips-to-improve-your-ux-strategy-5e39f5ff0a41#.n103o5inc"
}
]}
}
})
If you need to write code like <Card key={index} index={index} item={item}/>, all you need to do is just extract your card html code to a component's template.
Vue.component('card', {
template: '<div>A custom component!</div>'
})
In addition to seaify's answer, if you register card as a component and iterate via v-for
Vue.component('card', {...})
<card v-for="resource in resources">
...
</card>
then you have to take care of that you may have some performance issues because of the reactivity system. In Vue.js, initializing a component is a little bit expensive.
If you really need to iterate a component, you should use a functional component: https://vuejs.org/guide/render-function.html#Functional-Components
Iterating a normal component is about 6~10x slower than functional component on my computer. Here is a simple performance test, iterate a component 2000 times (about 400 ~ 600 ms):
(open dev console to see the result)
http://codepen.io/CodinCat/pen/yaGAWd?editors=1010
vs functional component (about 40 ~ 60 ms):
http://codepen.io/CodinCat/pen/XjowAm?editors=1010

Issue with Highcharts not rendering in Durandal/Hot Towel Template

We're using HighCharts.js in a Durandal/Hot Towel template in ASP.NET MVC 4. We are simply showing a proof of concept in using a charting API for a dashboard page. However, the graph is not rendering on the page during page load.
We have a custom .js file that holds the following code (copied and pasted from HighCharts.com):
$(document).ready(function () {
$('#reportgraph').highcharts({
chart: {
type: 'bar'
},
title: {
text: 'Fruit Consumption'
},
xAxis: {
categories: ['Apples', 'Bananas', 'Oranges']
},
yAxis: {
title: {
text: 'Fruit eaten'
}
},
series: [{
name: 'Jane',
data: [1, 0, 4]
}, {
name: 'John',
data: [5, 7, 3]
}]
});
});
And a div in an HTML view that is rendering correctly:
<div class="row-fluid">
<div class="span12">
<div class="widget">
<div class="widget-header">
<div class="title">Highcharts</div>
</div>
<div class="widget-body">
<div id="reportgraph" style="width:100%"></div>
</div>
</div>
</div>
</div>
The script bundler contains the following files:
.Include("~/Scripts/jquery-1.9.1.min.js")
.Include("~/Scripts/highcharts.js")
.Include("~/Scripts/custom.js")
.Include("~/Scripts/bootstrap.js")
.Include("~/Scripts/knockout-{version}.debug.js")
.Include("~/Scripts/sammy-{version}.js")
.Include("~/Scripts/toastr.js")
.Include("~/Scripts/Q.js")
.Include("~/Scripts/breeze.debug.js")
.Include("~/Scripts/moment.js"));
Yet the graph does not render. I've been able to successfully render the graph in a Bootstrap application, working with the scripts listed above.
Is there an extra step that must be done in order to work with functions inside document.ready statements on a single page application?
Thanks in advanced!
In a typical Durandal app there's no need to use document ready as at that point only the content of index.html (applicationHost) has been rendered. Everything else gets injected into the DOM by using Durandal's composition.
In order to work with these composed DOM fragments add a viewAttached callback in the vm that accompanies the html view. viewAttached gets the composed view passed in as parameter, which should be used to restrict the jQuery selector.
function viewAttached(view) {
$('#reportgraph', view).highcharts({
...
});
};
In most instances that should be sufficient to get jQuery plugins working. However in Durandal 1.2 viewAttached just ensures that the composed fragment is attached to its parent element not necessarily to the DOM, so you'd have to check if this is sufficient to get highcharts working. That issue will be addressed in upcoming Durandal 2.0 by introducing a documentAttached callback.