Are custom attribute bindings possible with Vue templates? - vue.js

I'm trying to bind a custom attribute value in my Vue template. How can I do this?
(EDIT: The following code actually binds correctly. A third party library (Foundation) was interfering with the binding. Leaving the question up as it may be useful to others.
<template>
<span v-bind="{ 'aria-controls': inputControlId }"></span>
<input v-bind="{ 'id': inputControlId }">
</template>
<script lang="ts">
import Vue from 'vue';
import Component from 'vue-class-component';
#Component
export default class Slider extends Vue {
inputControlId = "TheBourneId";
}
}
</script>

The common syntax for binding attributes is
<template>
<span v-bind:aria-controls="inputControlId"></span>
<input v-bind:id="inputControlId">
</template>
There is also a shorthand.
<template>
<span :aria-controls="inputControlId"></span>
<input :id="inputControlId">
</template>
You can bind multiple properties at once using the syntax in your question, it's just not commonly used outside class or style, especially for single attributes.
It sounds like the real issue was your CSS framework.

Related

Vue: bind dynamic and static classes

A bit new to Vue so I am looking for a better way(if there's one) to set a default class without using the class attribute twice.
Component.vue
<template>
<input class="form__control" :class="class" v-bind="$attrs"/>
<template>
<script>
export default {
props: ['class']
}
<script>
Usage
<component class="big-red" data-id="1" type="text"/>
You can bind dynamic and static classes within a single property, using the array declaration:
<template>
<input :class="['form__control', class]" v-bind="$attrs"/>
<template>

How to use Vue I18n translation in component attribute/property

How do I translate the passed-in attribute/property of a component? For instance, I have a card component with a title and description prop defined like this.
<!-- my-card component -->
<template>
<div>
<h2>{{title}}</h2>
<span>{{description}}</span>
</div>
</template>
<script>
export default {
props: {
title: String,
descritpion: String
}
}
</script>
Then using the my-card component in another page/component like this
<template>
<div>
<header>Page header</header>
<my-card :title="the best card title" :description="the best description" />
<footer>Page footer</footer>
</div>
</template>
How do I us vue I18n to translate the component props?
<template>
<div>
<header>Page header</header>
<my-card :title="{{ $t('myCard.title')}}" :description="{{$t('myCard.description')}}" />
<footer>Page footer</footer>
</div>
</template>
I can't seem to get the translation to work with passed-in props.
PS: I know I could add the translation in the place I defined my-card component but the issue here is that the components are third-party components from NPM library.
I know some packages in React.js has this feature.
Just bind the translation without using {{}} :
<my-card :title="$t('myCard.title')" :description="$t('myCard.description')" />
You can use I18n translation in component props like this.
<my-card
:title="$t('myCard.title')"
:description="$t('myCard.description')"
/>

How do I provide the component that is replacing <slot> with properties?

I have a component that functions as a basis for other components.
//The Basis Component lets call it slotComponent
<template>
<div>
//somestuff
<slot :someProperties="someLocalValues"></slot>
</div>
</template>
As you can see I want to give the component that is replacing the slot some Properties that only this component will know.
However if I do this:
//Some page Component lets call it mainPage
<template>
<slotComponent>
<someOtherComponent/>
</slotComponent>
</template>
Then "someOtherComponent" will not have access to "someProperties". How can I provide this component with said property?
Note that someLocalValues are defined in the scope of slotComponent and not its parent. So I cant provide said information in the mainPage.
You need to specify the v-slot directive in order to bind the props. Check the documentation here: https://v2.vuejs.org/v2/guide/components-slots.html#Scoped-Slots
You also will need to pass the props to your child component.
In your example, you would need to do something like:
<template>
<slotComponent>
<someOtherComponent v-slot="slotData" :data="slotData.someProperties"/>
</slotComponent>
</template>
This is the same, but with an additional <template> for clarity:
<template>
<slotComponent>
<template v-slot="slotData">
<someOtherComponent :data="slotData.someProperties"/>
</template>
</slotComponent>
</template>

control over inherited attributes by vue component

Is there a way to have control over attributes provided through the component tag?
For example:
<my-component class="myClass" style="myStyle"></my-component>
My component:
<template>
<div>
<div>
</div>
<div>
</div>
</div>
</template>
At render Vue applies given attributes on the root:
<div class="myClass" style="myStyle">
<div>
</div>
<div>
</div>
</div>
I want to control where those attributes are applied like so:
<div>
<div>
</div>
<div class="myClass" style="myStyle">
</div>
</div>
#Boussadjra Brahim answer is definitely one way to handle it, however this will require you to pass in all of the class attributes you want everytime you define the component.
This question is answered in this SO post already as well.How to style a nested component from its parent component in Vuejs?
If you want a bit more flexibility I would suggested using interpolation and properties as below. This will let you define some default classes and pass in whatever else in addition.
<app-header :headerclass="parent-header-class"> </app-header>
Inside of your child component, you can use these properties and v-bind the class inside the HTML, as shown in the example below:
<template>
<div :class=`${headerClass} internal-class-example button`> </div>
</template>
Note: This does not allow you to use any scoped parent CSS to pass to the child. The classes you pass down must be global. Otherwise, the child component will not know what it is.

v-if on a component template tag

From the docs:
Because v-if is a directive, it has to be attached to a single
element. But what if we want to toggle more than one element? In this
case we can use v-if on a element, which serves as an
invisible wrapper. The final rendered result will not include the
element.
But on my template in my component:
<template v-if="false">
<div>
....
</div>
</template>
But the component still renders.
I ask because I want a hook on the component so if v-if is true, I can do some code in beforeMounted and beforeDestroyed if false.
If I undestood what are you doing...
You're putting v-if int the template tag ina .vue file right?
Like this
// component.vue
<template v-if="false">
<div>
My Component
</div>
</template>
<script>
export default {
name: 'my-component'
};
</script>
<styles>
</styles>
Right?
If YES, you are doing it wrong.
The template there is a tag for Webpack Vue Loader to load the component template.
So the if must go inside the template tag.
// component.vue
<template>
<div v-if="false">
My Component
</div>
</template>
<script>
export default {
name: 'my-component'
};
</script>
<styles>
</styles>
If you need to "hide" multiple elements, just encapsulate into another div.
As Lucas Katayama said, you cannot use v-if inside SFC, but another way to hide you component is use v-if on this component in its parent component.
Your reference to the docs is correct, you can use a v-if on a template tag. However, I believe conditionals on the top-level <template> in a Single File Component are ignored.
To achieve the effect showed in the docs (conditional render a template) that template needs to be within the top-level template section.
Example:
<script>
// your script section
</script>
<template>
<template v-if="false">
<div>
....
</div>
</template>
</template>
<style>
// your style section
</style>