Most of us focus on solving little problem after little problem, forgetting about the architecture of your application and neglecting how important it is to structure the data right for our needs - be it in a database or in a view/page.
Don't get me wrong, breaking your big, impossible mission into little ones IS the way to go. All I'm trying to say is: do not lose sight of the bigger picture: you deliver code that, in the end, solves a problem for somebody ( let's call that somebody our "client" ). As time passes, the client will have different needs - there is no "maybe" in there, trust me! - so you must anticipate as much of it as possible.
As for the part you can not anticipate, you must have the possibility of extending / modifying the app as the requirements change in a way that does not break it and in a reasonable time frame. "Testing" sounds cool in this situation? Spare the unicorns and rainbows, most likely your app does not have the needed tests. If you are part of the happy ones, keep reading anyway, this applies for apps that are test-covered as well.
Enough with the theory, time for real-life example.
Let's say we have to display more or less the same data in different ways, based on some flags / conditions - whatever you may want to call them.
Where these flags come from is irrelevant. They might be a filter a user applies in the page, or it could be an admin wanting to change the way a page looks every time he feels like it. In the end, all that matters, is the flag - true or false, vertical or horizontal, black or white.
VueJs is beautiful and awesome. "Magic", some might say. But it is like this because it takes care of the rendering and updates. It is your responsibility to give it data in the right format.
Let's say we have to display a list of products by category. Of course, that means we are going to need an object that looks more or less like this:
const displayProducts = {
"Category1": [ PRODUCTS ],
"Category2": [ PRODUCTS ],
}
This is fine, but what happens if we want to display the products by their color, or by some rank, or in a random order? Sure, we can parse the displayProducts
and get a products array containing all the products.
But that's exactly the problem. You already have to parse your own data before being able to actually use it. When that happens, I think you should take a step back and reconsider what you're doing.
Take a second and think about the actual problem : you have to display a list of products . PRODUCTS, not categories. So our main data source and point of truth should be... well, yeah, products.
Now, being in Vue, a data-centered framework, we're good to go. We have an array of products that contain their infos: tags, category, rank, if they are featured or not, etc. Having all the data in one place, it is actually quite easy to display it in different ways to the end user.
Displaying the products markup is pretty much the same in all cases, but it can be customized depending on your needs - not going into details as article would get waaay too long. Each different listing could be a standalone component getting a list of products as props, and this component could render a list of product
components. A basic listing would look like this:
<template v-if="groupType === 2">
<template v-for="tag of orderedTags">
<br>
<b>{{tag.label}}</b>
<br>
<template v-for="(item, index) in productsTagged(tag.id)">
{{ item.name }}
<br>
</template>
</template>
</template>
Let's say we want to display the products by tag. Our computed that returns the products is as simple as this:
productsTagged(tagId) {
let itemsWithTag = [];
for (let item of this.products) {
if (item.tags.indexOf(tagId) !== -1) {
itemsWithTag.push(item);
}
}
return itemsWithTag;
},
Still not convinced? Here's how easy it is to change the ordering of the whole page, when your client decides in the middle of the night that he wants the green products to be displayed first and the red ones third :
orderedTags() {
let collectedTags = coll(this.tags);
return collectedTags.sortBy("position").all();
},
Ok, now it's 2 o'clock in the morning and he doesn't give a single **** about the red and green products. Now he has some favorite tomatoes and some good tasty bacon that he wants displayed first. What do we do ? Change the front-end page to display 2 "different" types of products, that perhaps come from 2 requests like getFeaturedProduts
and getOtherProducts
?
Now someone - be it you or somebody else - needs to go into the backend code of your application and expose the same data in 2 different ways.
Or.... we could have the data and app structured the right, scalable way.
<template v-if="groupType === 3">
<b>Our most bought products</b>
<br>
<template v-for="item in byFeaturedOption(true)">
{{ item.name }}
<br>
</template>
<hr>
<template v-for="item in byFeaturedOption(false)">
{{ item.name }}
<br>
</template>
</template>
And our filtering function:
byFeaturedOption(option) {
let collectedProducts = coll(this.products);
let itemsByCat = collectedProducts.where("featured", option);
return itemsByCat.all();
}
What is that coll, you might wander ? It is nothing else than collect.js
, a very nice and dependency free js library for lazy people, like myself. It provides convenient query functions over collections of data - 99% similar with the eloquent collections from laravel, as they are inspired from those.
Now you could write your own filtering and sorting functions, or you could use helpers like collect.js
. It is entirely up to you. If you structure your data right and you have it in a "raw" form, you then have the liberty of manipulating it as you may wish, without having to modify half of your application's structure for every single change.
The snippet is beginner-oriented, while the purpose of the article is to make everyone realize how important it is to architecture your app right. This applies to so much more than a simple js-rendered list of products, but I think the VueJs examples are the easiest to understand and follow.
Full snippet can be found here:
https://codepen.io/costicaaa/pen/bZWGoB
As always, feedback and questions are more than welcome.
Cheers : )
Top comments (0)