Does Meteor Enforce CamelCase for Template Names? - javascript

So I've a route called 'find_project' as follows:
Router.map(function() {
this.route("/find_project");
}
And my template is as:
<template name="find_project">
<h1>Find project page</h1>
</template>
Obviously, one would expect the template to work, right? NO!
Couldn't find a template named "FindProject" or "findProject". Are you sure you defined it?
Now I camel-case the template name like so:
<template name="findProject">
<h1>Find project page</h1>
</template>
And magically, it started working.
Does Meteor enforce camel casing in template names?

Meteor does not enforce camel-cased names, the problem you're facing comes from iron:router trying to guess the template name from the route path, using a camel-cased heuristic by default.
If you prefer underscore based names, rewrite your routing function as :
Router.route("/find_project",{
template:"find_project"
});

Router.setTemplateNameConverter(_.identity);
from: https://github.com/EventedMind/iron-router/issues/1064

Related

how to compile time check strongly typed props in vue templates?

Using Vue with Typescript makes it possible to specify types for props: Strongly typing props of vue components using composition api and typescript typing system
However, as far as I can see these props are only checked at runtime. Here's a simple example component. It has two props a, and b. One is a number and the other a string. Additionally b has a validator, it is only valid if it's equal to hi
<template>
<p>{{a}}</p>
</template>
<script>
import {defineComponent} from 'vue';
export default defineComponent(
{
name: "TestComp",
props:{
a:number,
b:{
type: String,
validator:(val)=>val=="hi"
}
}
}
)
</script>
Here's how you could (incorrectly) use the component. The prop a has a wrong type and the prop b fails its validation:
<TestComp a="hi" b="ho"/>
Is it possible to find this bug at compile time?
Out of the box, Vue only complains at runtime, with a message such as Invalid prop: custom validator check failed for prop "b".
After searching online, I found that prop type validation can be switched on as an experimental Vetur feature. But this doesn't call the custom validator, so in the example above, Vetur can't find the problem for b.
Also, I'm not always using Vetur and would prefer to have the wrong types trigger an actual compile time error.
For (a): Type definitions
The Typescript / Vue Template compiler does not check for this.
Why? Because the type information is not available to the template compiler.
It is possible to analyze this outside the "normal" template compiler. WebStorm has a check for this.
For (b): Validator
The validation is done at runtime and cannot be checked at compile time.
You can write many of those assertions by adding the exact type to the prop, then WebStorm can check them. When using type checks, it is best use typescript (although you can use /** #type */ comments, too)
<script lang="ts">
import {defineComponent} from 'vue';
export default defineComponent(
{
name: "TestComp",
props:{
b:{
type: String as PropType<"hi">,
validator:(val)=>val==="hi"
}
}
}
)
</script>
Try vue-tsc. It's a part of Vite vue-ts preset that allows to check Vue templates on compile. I was going to use Vite along with Webpack just for templates type checking, but it seems like vue-tsc can do it by itself. However Vite CLI makes configuration easier as it provides all the base TS config, so we only need to compare with already existed tsconfig and take what we need.

How to detect if vue-router is used in current Vue instance?

I want to develop a library with vue.js component inside. This component will have navigation elements inside. I want it to work with and without vue router. In router mode it should use <router-link> and if no router is used it should return standard <a> tags.
<template>
<div>
<div v-if="vueRouterIsUsed">
<router-link v-bind:to="url">Router link</router-link>
</div>
<div v-else>
<a :href="url">No router</a>
<div>
</div>
</template>
<script>
export default{
props: {
url: {
type: String,
}
}
}
</script>
How to detect if vue-router is used in current Vue instance?
Is there a better way that if/else for doing <router-link> to <a> fallback if no router is installed?
You can check in the created (or mounted) lifecycle hook what is in this.$router you can access all the routes and the router object, which means you can check what you need. Set the isRouter variable based on that.
If you are using Vue3, you can use getCurrentInstance like this :
const isVueRouterInstalled =
!!getCurrentInstance().appContext.config.globalProperties.$router;
However, as the documentation says :
getCurrentInstance is only exposed for advanced use cases, typically in libraries. Usage of getCurrentInstance is strongly discouraged in application code

How do I register a Vue component?

I have the following files. All I want to do is to be able to create different components that are injected. How do I achieve this using require.js? Here are my files:
main.js
define(function(require) {
'use strict';
var Vue = require('vue');
var myTemplate = require('text!myTemplate.html');
return new Vue({
template: myTemplate,
});
});
myTemplate.html
<div>
<my-first-component></my-first-component>
</div>
MyFirstComponent.vue
<template>
<div>This is my component!</div>
</template>
<script>
export default {}
</script>
I'm going to assume you're using webpack as explained in the Vue.js docs, or else your .vue file is useless. If you're not, go check how to set up a webpack Vue app first, it's what lets you use .vue files.
import Menubar from '../components/menubar/main.vue';
Vue.component('menubar', Menubar);
That's how you add e.g. a menubar component to the global scope. If you want to add the component to just a small part of your app, here's another way of doing it (this is taken from inside another component, but can be used in exactly the same manner on your primary Vue object):
import Sidebar from '../../components/sidebar/main.vue';
export default {
props: [""],
components: {
'sidebar': Sidebar
},
...
You can load components without webpack, but I don't recommend it, if you're gonna keep using Vue (which I strongly suggest you do) it's worth it to look into using webpack.
Update
Once again, really, really, really consider using webpack instead if you're gonna be continuing with Vue.js, the setup may be slightly more annoying but the end result and development process is waaaay better.
Anyway, here's how you'd create a component without webpack, note that without webpack you can't use .vue files since the .vue format is part of their webpack plugin. If you don't like the below solution you can also use e.g. ajax requests to load .vue files, I believe there is a project somewhere out there that does this but I can't find it right now, but the end result is better with webpack than with ajax anyway so I'd still recommend going with that method.
var mytemplate = `<div>
<h1>This is my template</h1>
</div>`
Vue.component('mycomp1', {
template: mytemplate
});
Vue.component('mycomp2', {
template: `
<div>
Hello, {{ name }}!
</div>
`,
props: ['name'],
});
As you can see, this method is A LOT more cumbersome. If you want to go with this method I'd recommend splitting all components into their own script files and loading all those components separately prior to running your actual app.
Note that `Text` is a multi line string in javascript, it makes it a little easier to write your template.
And as I said, there is some project out there for loading .vue files using ajax, but I can't for the life of me find it right now.

How to translate using flask-babel on javascript?

I have a python project with jinja templates and flask-babel working good.
My problem are javascript files. I have all the js files inside a folder called 'static', but after using:
var food = gettext('food');
Then updating and compiling, the browser returns an error :
gettext is not defined
I've seen some projects using babel.js or jsil18n but I'm not sure if I really need that. How can I define gettext the same same way I did with my jinja templates?
If food is a string, then you can use the following syntax provided you have the translation for food in your messages.po file:
var food = "{{_('food')}}";

iron-router does not render template in Meteor

I have installed the atmosphere package iron:router for my meteor application. I am trying to add a simple route like this:
Router.configure({
layoutTemplate: 'layout',
loadingTemplate: 'loading',
notFoundTemplate: 'notFound'
});
Router.route('/', {
name : 'homeIndex'
});
I defined a template:
<template name="homeIndex">
<h1>Test for my meteor application</h1>
</template>
And I add a yield - field to my layoutTemplate:
<template name="layout">
<div class="container">
{{> yield}}
</div>
</template>
But still when I go to '/', I don't see anything of my template.
Also when I'm trying to add another route with another template, it doesn't work. I have installed the package through this command: meteor add iron:router
Can someone please tell me what I'm doing wrong?
If you want to render a template when a user goes to a particular route, you should use this.render('templateName');. In your case, you only defined a named route, but you didn't specify which template to render.
Router.route('/', function () {
this.render('homeIndex');
}, {
name: 'homeIndex'
});
When I looked at my console in the browser, I saw the iron router package was throwing an exception that EJSON was undefined in the javascript of the package. I installed the EJSON package with the command meteor add ejson, and it was fixed! But thanks anyway for the help!

Categories