How to pass route parameters as numbers? - vue.js

In the section Passing Props to Route Components of Vue documentation, they explain how to pass a parameter from the location path into the component, and they declare the props as an array. But in the Style guide, they mention it is preferable to have props define (at least) their data type.
If i were to listen to the style guide, and if i wanted my URL to define id's of the entities they want to refer to (for example /user/99), then how would i pass that parameter as a number, and avoid the console error telling me it expected a number, but got a string? There are no examples of this.
In the line { path: '/user/:id', component: User, props: true }, i would need some extra parameters specifying that id is of type Numeric. But how exactly?

You can create a function that returns props. This allows you to cast
parameters into other types, combine static values with route-based
values, etc.
Reference.
const router = new VueRouter({
routes: [
{
path: '/user/:id',
component: User,
props: route => ({ id: Number(route.params.id) }),
},
],
})

Related

Declaring props in array vs array of objects

I just found out that instead of defining the properties of a component like so:
const props = defineProps({
id: Number,
title: String,
name: String,
})
I can do this instead:
defineProps([
'id',
'title',
'name',
])
This doesn't seem to require type declaration but is there any downside to doing this? Does vue determine the type of each property by itself?
I'm using script setup.
Downside is of course less safety.
Does vue determine the type of each property by itself? No
When providing array of strings, Vue does not validate the type of passed props at all so in case of incorrect usage (which is much more likely to happen as other devs/future you are not able to tell what should be passed in without reading the rest of component's code) you end up with some runtime error somewhere in your component instead of clean error/warning about wrong value passed as prop (or a sensible error from your IDE)
You should use as much specific props definition as possible most of the time.
Well it's not just type declaration.
It is a prop validation feature.
The complete syntax is
const props = defineProps({
name: String,
id: [ Number, String ],
style: {
type: Object,
default: ()=>{
color: "red",
bg-color: "white"
},
validator: function (value) {
return ['red', 'blue', 'green'].includes(value.color)
}
},
})
So the downside of using just the named props is:
No type safety. But even in case of typed props it will only show console warning in development build.
Whereas the advantage of using prop definition is
Multiple types for single prop
Default value for a prop
Custom validator function

Can we use props to pass variable in vue?

Slall question:
I have a 2 parent components nesting the same child component inside of them.
I use props so the parents can tell the child what title to show.
this child component is a photo gallery. It makes a query to the database, download photos and show them up. classic.
I need the parents to tell the child where to get the photos from:
Get the photos from All users, for the home page
or
get only the photos from a specific user for a user's page.
I'm wondering if I can pass this information through a prop.
Is that possible? Can we use the info from a prop as a varialble inside of the setup() function?
Is there a better way to do this?
Passing objects from one component to a child component is the purpose of props.
You can pass many items through props. VueJS has the following types built-in:
String
Number
Boolean
Array
Object
Function
Promise
In the V3 VueJS guide it gives the following example of a prop being passed into a component and then being logged to the console inside the setup() method.
export default {
props: {
title: String
},
setup(props) {
console.log(props.title)
}
}
However, when using props, you should always mark whether the is required, what its type is and what the default is if it is not required.
For example:
export default {
props: {
title: String, // This is the type
required: false, // If the prop is required
default: () => 'defaultText' // Default needed if required false
},
setup(props) {
console.log(props.title)
}
}
It's important to note that when using default, the value must be returned from a function. You cannot pass a default value directly.

(vue router) Is there a neat way to not duplicate code when creating two routes with an almost identical view?

I have a NewArticleView vue component that is mapped to /articles/new, like this:
const routes = [
...
{
path: '/articles/new',
name: 'New Article',
component: NewArticleView
},
...
]
The view is basically just a form.
I want to create an EditArticleView component but it feels wrong making a new component, since it will be almost identical to NewArticleView.
I really wish there was a way to send an edit flag or something when navigating to the route (something like router.push('/articles/new', editArticle=true)), which modifies the behaviour of the component. Like binding form values to the article I want to edit, instead of an empty form, and use an update api call instead of the one used for creating a new article.
Is there a neat way to do this?
You could make one component like ArticleView which accepts a prop named editArticle :
{
path: '/articles/new',
name: 'ArticleView',
component: NewArticleView,
props: route => ({ editArticle: route.query.editArticle})
},
then use it like /articles/new?editArticle=true

VueJS - updating URL with dynamic data

I have a single page VueJS app with a number of data variables I want to encode into the URL.
As an example if my route configuration is (I'm not sure if the syntax is correct):
routes: [
{
path: '/:foo/:bar/:oof/:rab',
component: App
}
And the Component is:
<script>
export default {
name: "App",
data: function() {
return {
foo: 1,
bar: 2,
oof: 3,
rab: 4
}
}
}
Then the URL would be http://www.example.com/#/1/2/3/4
And if foo is changed to 9999 the URL would automatically update: http://www.example.com/#/9999/2/3/4
It would also respond to the user changing the URL, or opening the app with a different URL by loading the URL values into the data.
I thought this would be relatively straightforward but after a Google I'm utterly confused by the correct way of going about this.
Any help/ examples/ solutions greatly appreciated.
Whatever you use to change the values would need to trigger a route push. For example
methods: {
changeFoo (newFoo) {
// you can set foo but it probably won't matter because you're navigating away
this.foo = newFoo
this.$router.push(`/${newFoo}/${this.bar}/${this.oof}/${this.rab}`)
}
See https://router.vuejs.org/guide/essentials/navigation.html
It might be easier if you name your route, eg
routes: [{
name: 'home',
path: '/:foo/:bar/:oof/:rab',
component: App
}]
then you could use something like
this.$router.push({name: 'home', params: this.$data})
It seems that there are two things you're trying to achieve, but I'm not sure from your example which comes first in your ideal order of operations:
Getting the values from your URL
This can be achieved through this.$route.params, which will be an object containing the values you're looking for.
Setting the URL based on your foo, bar, oof, rab variables
You can use this.$router.push() to do this: vue-router docs

How can I define props?

I've seen props being define like:
props: ['message', 'name', 'something']
and
props: {
imperfectNumber: {
type: Number,
required: true
}
}
Whats the difference and how can I define some props that require no validation and others that do all in the same block?
Once you go down the object definition route, you have to do that with all the props. You can't mix them.
You can find more information about the props here: https://v2.vuejs.org/v2/guide/components.html#Prop-Validation
Note:
Instead of defining the props as an array of strings, you can use an
object with validation requirements
I've highlighted the part in the manual that explains. This indicates you can do one or the other.