DRY for displaying meteor templates for different urls - dry

I am having trouble setting up a simple website with different webpages and staying DRY.
I have everything set up so I the last fragment of the url is the name of the template that needs to be loaded in the content part of the webpage. All I want to do now is load that template in a specific location based on the url.
In any examples, they do this:
{{#if showCreateDialog}}
{{> createDialog}}
{{/if}}
{{#if showInviteDialog}}
{{> inviteDialog}}
{{/if}}
I'd like to do something along the lines of
{{> {{template_name}} }}
Sadly, that doesnt work. I tried this as well:
{{{content}}}
Template.content.content = function () {
var url_frag = Session.get("url_frag");
return Template[url_frag]();
}
This didnt work either. Please help!
Edit:
hmm. perhaps, my error is not in loading the template but in capturing the url:
var TodosRouter = Backbone.Router.extend({
routes: {
"*url": "main"
},
main: function (url) {
Session.set("url", url.split('/'))
}
});
The error I am getting arises when url_frag is undefined...
var url_frag = Session.get("url_frag");
initially, this works, but upon changing webpages, it fails...

Solved. I just left backbone out of it
Template.content.content = function () {
var url = window.location.pathname.split('/');
var url_frag = url.pop()
return Template[url_frag]();
Then in the html:
<template name="content">
{{{content}}}
</template>

You could also try the router smart package at atmosphere, which also supports complex routes and filters.
https://atmosphere.meteor.com/package/router
Install meteorite using npm install -g meteorite
Install router using mrt add router
Add {{renderPage}} to body
Tada! /login now renders {{> login}}
Read the document here: https://github.com/tmeasday/meteor-router

Related

How to redirect to router.base URL in NuxtJS

Let's say my nuxt app is running in a subfolder 'test'.
nuxt.config.js:
router: {
base: '/test/'
}
That means my application runs on localhost:3000/test
Now, when I go to localhost:3000/tes, all i get is a 404 Error with the contents Cannot GET /tes
However, I want to redirect to /test, or show my own 404 page. But I couldn't figure out a way to handle that case.
I tried using a middleware, but that only worked for links within the subfolder.
Thanks for your help!
I found what I needed in the nuxt documentation:
Using a Hook to router.base when not on root:
https://nuxtjs.org/docs/configuration-glossary/configuration-hooks#redirect-to-routerbase-when-not-on-root
You can create an error layout for the 404 page
Error page
Or you can use middle to check the incoming URL and redirect them somewhere.
Middleware
You can create your error layout (error.vue in layout folder) and when error it will show that page.
<template>
<div>
<h1 v-if="error.statusCode === 404">Page not found</h1>
<h1 v-else>An error occurred</h1>
<NuxtLink to="/">Home page</NuxtLink>
</div>
</template>
<script>
export default {
props: ['error'],
layout: 'error' // you can set a custom layout for the error page
}
</script>
Link showing practically how to do that: medium

Dynamically add json content with vue-if and other vue attributes

I am working chrome extension which uses vue. I have found that google can take a while to publish updates, so there is some content that I would like to be able to edit with a json that is called by the extension via a $.getJSON https request. So far, that has worked pretty well for getting raw text. But I have problems when I try to add a span tag with a v-if statement such as the following:
Thank you for meeting. We have prepared the following <span v-if='docCount.length > 0'>documents</span><span v-else>document</span> for you today:
What happens is that it just says "prepared the following 'documentsdDocuments'" as if it takes all to be true.
I have gotten this result after putting the above JSON text in a v-html as follows:
<p v-html="coverLetterContent['p1']"></p>
I have gotten the same result after trying the following:
.bind(this)).then( function (result){
$(".letter-body").append("<p>"+result["letter"]["p1"]+"</p>")
});
I also tried creating a dynamic component as follows but was getting an error and nothing was rendered:
dynamicComponent: function() {
return {
template: `<p>${coverLetterContent["p1"]}</p>`,
methods: {
someAction() {
console.log("Action!");
}
}
}
}
The error I got on this was: "ReferenceError: coverLetterContent is not defined." coverLetterContent is defined in the vue app data and is accessible via the v-html call described above.

Vuelayers vl-style-icon syntax

I've been looking through the vuelayers documentation and have found little info on to use the vl-style-icon module, which is quite important if you want to create icons on your vuelayer map.
I'm pretty sure I have proper syntax when it comes to using it but marker.png won't load in through it. I've tried accessing it as just a normal image and it works fine so it is to my assumption that it's something with my syntax.
Here is my code:
<template>
<vl-map :load-tiles-while-animating="true" :load-tiles-while-interacting="true" style="height: 400px">
<vl-view :zoom.sync="zoom" :center.sync="center" :rotation.sync="rotation" projection="EPSG:4326"></vl-view>
<vl-feature v-for="crime in crimePoints" :key="crime.id">
<vl-geom-point :coordinates="crime.coords"></vl-geom-point>
<vl-style-box>
<vl-style-icon src="./marker.png" :scale="0.4" :anchor="[0.5, 1]"></vl-style-icon>
</vl-style-box>
</vl-feature>
<vl-layer-tile>
<vl-source-osm></vl-source-osm>
</vl-layer-tile>
</vl-map>
</template>
vl-style-box and vl-style-icon are the main points here. I have also checked to see if the points come up without vl-style-box and they do. What could be wrong with my code?
You can try like this:
<vl-style-icon :src="require('./marker.png')" :scale="0.4" :anchor="[0.5, 1]"></vl-style-icon>
</vl-style-box>
If you used Vue CLI to create your vue project include this in your vue.config.js file. First section tells webpack to parse url attribute on custom tags other than what is already configured (Source).
module.exports = {
chainWebpack: config => {
config.module.rule('vue').use('vue-loader').tap(options => {
options.transformAssetUrls = {
'vl-style-icon': 'src',
...options.transformAssetUrls,
};
return options;
});
}
}
Run the following command to verify the correct vue-loader configuration is there
Source
vue inspect > output.js

Vue cli image wont load with webpack

What am I doing?
I am using the intersection observer API to make lazy loading.
What have I tried?
I tried the code in a simple HTML page and it works perfect, but when I use the code in vue, the images won't load (local images). If I put a htttp source images (online images) it works perfect, too. I think this is a webpack error config. Am I right? How can I fix it?.
Whats the error?
When i use a local image the code doesnt work, if only change that src with something else like this image https://images.pexels.com/photos/69817/france-confectionery-raspberry-cake-fruit-69817.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940 the code WORKS, why i cant make it work with local images?
HTML AND SCRIPT
<template>
<div class="container" id="section3">
<span class="containerTitle">Galeria</span>
<div class="wrapper">
<img v-lazyload data-src="#assets/images/001.jpg" class="card">
</div>
</div>
</template>
<script>
import lazyload from '../directives/lazyload'
export default {
directives:{
lazyload
},
}
</script>
DIRECTIVE
export default{
inserted: el =>{
const options = {
// root:
rootMargin: '0px 0px 0px 0px',
threshold:1
}
var observer = new IntersectionObserver((entries,observer) =>{
entries.forEach(entry => {
if(entry.isIntersecting){
el.src = el.dataset.src
observer.unobserve(el)
console.log('intersecting');
}
})
},options)
observer.observe(el)
}
}
CODE IMAGE
FOLDER
The issue is with your image path.
You can fix it with either using public folder and give it in path.
You can also check for auto suggestion which come up while typing, this may help you to check whether your path is correct or not.
Like this
Your path is wrong. You gave ../assets/images/001.jpg as the path to the image (as stated in your question), but according to your directory tree it's ../assets/001.jpg (or write it like #/assets/001.jpg, # points to root of project). That should fix it.
As far as I remember you can't use # sign inside <template>.
So you can either:
require it
<img v-lazyload :data-src="require('#assets/images/001.jpg')" class="card">
import it
<template>
...
<img v-lazyload data-src="image" class="card">
...
</template>
<script>
import img from '#assets/images/001.jpg';
...
data() {
return {
image: img,
}
}
...
</script>
use relative path
<img v-lazyload data-src="../assets/images/001.jpg" class="card">
You can check how it works in Vue docs
I can't remember why this works, but you need to use the following syntax:
<img v-lazyload data-src="~assets/images/001.jpg" class="card">
with the ~ replacing the ../.
I will update the answer if I figure out exactly why.
doing extensive research i found this article about vuejs and static assets.
https://edicasoft.com/weblog/2018/04/27/static-vs-srcassets-webpack-template-vue-cli/
They said that this kind of problems occurs "because" of webpack,like i though, so the solution for this (i hope not the only solution), but this is the solution so far...
QUOTE
All asset URLs such as , background: url(...) and CSS #import are resolved by Webpack as module dependencies like require('./logo.png').
We then use loaders for Webpack, such as file-loader and url-loader, to process them. Webpack template has already configured these loaders.
File-loader helps to determine the final file location and how to name it using version hashes for better caching. Thus you can put your static assets near your .vue files and use relative paths. There is no need to put them strictly into the ‘assets’ folder.
Url-loader helps to conditionally inline assets such as base64 data URL, reducing the amount of HTTP requests.
So what the hell should I do with it?
The answer is: put your assets in the ‘src’ folder.
I tested this and it works perfect BUT you CANT make a subfolder and this for me, is disorganized.
This is the final folder structure to get this done using intersection observer api as vue directive!

Headless CMS and static pages? Content updates?

I am trying to use my first Headless CMS and I've tried both Prismic.io and Contentful.
For instance, this is the code from Contentful guide:
asyncData({ env }) {
return Promise.all([
// fetch the owner of the blog
client.getEntries({
'sys.id': env.CTF_PERSON_ID
}),
// fetch all blog posts sorted by creation date
client.getEntries({
content_type: env.CTF_BLOG_POST_TYPE_ID,
order: '-sys.createdAt'
})
])
.then(([entries, posts]) => {
// return data that should be available
// in the template
return {
person: entries.items[0],
posts: posts.items
}
})
.catch(console.error)
}
This works fine and I am able to fetch my blog posts in
<article v-for="post in posts" :key="post">
<h2>{{ post.fields.title }}</h2>
<p>{{ post.fields.content }}</p>
</article>
However, if I generate static pages with Nuxt, I understood the page will still load the latest version of the content from Contentful when live, while instead it just keeps the static content fetched on the pages when generated.
Am I missing the main point here?
Thanks
What you discovered is correct. Nuxt in its current version makes requests to the contentful API when new navigations occur. Afaik there are plans to write the data to disk during build time (e.g. Gatsby does it like that) but these are not implemented yet.
Personally, I'm running my private blog on exactly this tech stack and there is a small time window where static pages and the dynamically loaded part are different. This wasn't a bit problem for me so far. I can understand though that this could cause troubles.