I am using Vue2 and Vuetify in a project. I would like to be able to use any icon from the Tabler icon library, like so:
<v-icon>custom-icon-name</v-icon
I do not want to use the custom component based system with:
<v-icon>$vuetify.icons.iconName</v-icons>
Conceptually, what would be some possible solutions? Will I need to create a module for this, and if so, what would be a good approach? Thank you for your time.
The option that technically is working for me—but will be tedious to do—is to implement a TablerIcon.vue component:
<template>
<div>
<template v-if="iconName=='Deg360ViewIcon'">
<Deg360ViewIcon :size="size" :stroke-width="strokewidth" />
</template>
<template v-else>
<QuestionMarkIcon :size="size" :stroke-width="strokewidth" />
</template>
</div>
</template>
<style>
</style>
<script>
export default {
name: 'TablerIcon',
props: ['iconName','size','strokewidth'],
data() {
return {
}
},
}
</script>
And then I call this with:
import TablerIcon from './TablerIcon.vue'
...
components: {TablerIcon},
<TablerIcon :iconName="'Deg360ViewIcon'" :size="24" :strokewidth="1.5"/>
This seems to be working with the npm package found here: https://www.npmjs.com/package/vue-tabler-icons
Related
I am trying to create a dummy vue page, were the different components used in the page like b-field ,b-table etc should be injected into the page in order to make things more dynamic. Currently the fields and components are defined in the template section of the .vue page.
<template>
<div class="container is-fluid">
<b-loading :is-full-page="true" :active.sync="this.isLoading"></b-loading>
<p class="subtitle">Business Unit</p>
<b-field label="Business Unit">
<b-input
required
:disabled="this.newRecord ? false : true"
:value="this.objectData.id"
#input="(newValue)=>{updateValue(newValue,'id')}"
></b-input>
</b-field>
<b-field label="Description">
<b-input
:value="this.objectData.description"
#input="(newValue)=>{updateValue(newValue,'description')}"
></b-input>
</b-field>
<b-field label="Short Description">
<b-input
:value="this.objectData.shortdescription"
#input="(newValue)=>{updateValue(newValue,'shortdescription')}"
></b-input>
</b-field>
<b-field label="Status">
<b-autocomplete
:value="this.objectData.status"
:open-on-focus="true"
:keep-first="true"
:data="['Active','InActive']"
#input="(newValue)=>{updateValue(newValue,'status')}"
></b-autocomplete>
</b-field>
<section>
<p class="is-size-7 has-text-danger">{{submitError}}</p>
<b-button #click="submitForm" class="is-radiusless">Submit</b-button>
<b-button type="is-text" #click="$router.go(-1)" class="is-radiusless">Return</b-button>
</section>
</div>
</template>
<script>
import { viewMixin } from "../viewMixin.js";
const ViewName = "BusinessUnitDetail";
export default {
name: "BusinessUnitDetail",
mixins: [viewMixin(ViewName)],
};
</script>
But the components mentioned in the template section should actually be stored as a string and going forward in the future this string will be retrieved from the database instead. But for the time being and as a starting point , this string can be hardcoded in the script section itself. Now i need a solution or guidance on how to achieve this and make the page to actually work..
Note: Please note that in vue js, i know that we could show or hide components based on the application state using Vue conditional structures such as v-if and v-else. But this is not what iam talking about. Instead i want the components (b-field,b-table etc) to be dynamically injected into the DOM. So in future if there will be an extra b-field or any other component, i can simply append the component tag to the string and that new component will be rendered in the frontend successfully.Plz help?
I guess the solution you look for is vue dynamic components.
So you can do this:
<template v-for="(item, index) of components" :key="index">
<component :is="item.name" :any-prop="item.anyProp">
</template>
...
<script>
// ...
data() {
return {
components: [
{ name: 'b-field', anyProp: 'status' }
]
}
}
</script>
I am using vuetify version 2.3.10. I have a file with layout somewhat like this
<template>
<v-app>
<div>
<Users />
</div>
</v-app>
</template>
<script>
import Users from 'views/users.vue';
export default {
components: {
Users
},
</script>
But "Hello" doesn't show on the browser. But if I remove the tag something like this.
<template>
<div>
<Users />
</div>
</template>
Then in the browser I am getting this error. Cannot read property 'mobileBreakpoint' of undefined. Please help me resolve this issue.
users.vue(component)
<template>
<div>
<p>Hello</p>
</div>
</template>
index.js
The issue was here. I forgot to add vuetify : new Vuetify(), and the issue is resolved.
import Vue from 'vue';
import Vuetify from 'vuetify';
Vue.use(Vuetify);
new Vue({
vuetify : new Vuetify(),
...
});
In your Users component there should be an export default statement as well (without it you can't import it later) and give it the name: 'Users' for good measure as well. Then it should work as intended. Better also store your components in components. views are meant for everything that has an own route.
Users.vue
<template>
<div><p>Hello</p></div>
</template>
<script>
export default {
name: 'Users',
}
</script>
Other.vue
<template>
<v-app>
<div>
<Users />
</div>
</v-app>
</template>
<script>
import Users from '#/components/users.vue';
export default {
components: {
Users
},
</script>
I am in a process of migration of vuetify version 1.5 to 2.3 like you
in my case,
contains minus z-index
check your style sheet
i had a question about the v-edit-dialog component that vuetify offers. So, the way i am rendering my v-data-table is such that i am importing a component with props into a template slot. According to the documentation link, it seems like the data table has to be rendered directly, like this codepen.
So i am not sure how i can make the v-edit-dialog work using my approach.
Here is what my code looks like:-
<template>
<v-data-table>
<template v-slot:items="props">
<my-component
:protein="props.item.protein"
:carbs="props.item.carbs"
:fats = "props.item.fats"
:iron="props.item.iron"/>
</template>
<v-data-table>
</template>
I am sorry guys, i don't know how i can duplicate this issue but i hope you get some idea. Again, thank you in advance.
You should take a look at the documentation for component props.
What you have done by now is correct and should work, only if you have setup your component my-component correctly:
<!-- my-component example -->
<template>
<v-edit-dialog :return-value.sync="protein">
{{ protein }}
<template v-slot:input>
<v-text-field
v-model="protein"
:rules="[max25chars]"
label="Edit"
single-line
counter
/>
</template>
</v-edit-dialog>
</template>
<script>
export default {
name: 'my-component',
props: {
protein: {
type: String,
default: '',
}, //... the rest of the props you want to access
},
}
</script>
In order to make the protein and other props edit/mutate/update your props.item.protein etc, you have to add a sync modifier to the prop.
<template>
<v-data-table>
<template v-slot:items="props">
<my-component
:protein.sync="props.item.protein"
:carbs.sync="props.item.carbs"
:fats.sync="props.item.fats"
:iron.sync="props.item.iron"/>
</template>
<v-data-table>
</template>
Else, you will get a vue error "you should not mutate an prop directly"
<template v-slot:items="props">.
for this eazy right is
<template v-slot:items="{ item }">
<my-component
{{item. protein}}
After playing around with Aurelia for a while, i'm trying to creating a custom component/template. However with below minimal code i still cant seem to show the message that is in testcomponent.html. I see the <testcomponent></testcomponent> in html DOM, however not the message test. What am i doing wrong?
integrationcomponent.html
<template>
<require from="./forms/testcomponent"></require>
<h1>first page</h1>
<testcomponent></testcomponent>
</template>
testcomponent.js
export class TestComponent {
constructor() {
}
}
testcomponent.html
<template>
<p>test</p>
</template>
The classname is TestComponent; this tells Aurelia to look for test-component.html and test-component.js.
I think you can rename the class to 'Testcomponent' as well.
Aurelia is Convention over Configuration so you need to know the conventions.
Aren't there any error messages in the console?
I am trying to build a layout using single-file components in Vue.js, with dynamic population and URLs using Vue-router. (I'm using the webpack template via vue-cli as well.)
It works as expected for my app.vue file-- containing the nav, sidebar, page head, and <router-view>-- and the <router-view> content appeared as expected when the correct <router-link> is clicked... until I tried to add subcomponents to the add-load component being called to the <router-view>. Now, nothing appears at all, despite not throwing any errors.
Admittedly, I am not basing my structure on any examples, as I couldn't really find any doing it the way I was hoping to. I wanted to use nested components by calling them like custom elements-- I think this makes the code much easier to read and maintain. I'm not entirely sure how to structure it otherwise, to be honest. Using multiple <router-view>s as siblings to each other seems counterintuitive to me.
I've tried a variety of combinations of how and where to import and call the components, and nothing has worked. The only way I can get any content to load is if I only call a single component for path: '/add-load'. Is it just impossible to use multiple components outside of your base app.vue? I find that hard to believe. Here's what I started with.
From my index.js:
import AddLoad from '#/components/AddLoad'
import AddLoad from '#/components/ProgressSteps'
import Stops from '#/components/Stops'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
components: {
Sidebar,
TopNav,
MobNav,
PageHead
}
},
{
path: '/add-load',
components: {
AddLoad,
ProgressSteps}
}
]
})
From my App.vue file (the multiple component behavior that I'd like to mimic is shown here):
<template>
<div id="app">
<div class="wrapper">
<Sidebar/>
<div class="container-fluid">
<TopNav/>
<MobNav/>
<div class="container-fluid">
<PageHead/>
<router-view></router-view>
</div>
</div>
</div>
</div>
</template>
<script>
import Sidebar from '#/components/Sidebar'
import TopNav from '#/components/TopNav'
import MobNav from '#/components/MobNav'
import PageHead from '#/components/PageHead'
export default {
name: 'App',
components: {
Sidebar,
TopNav,
MobNav,
PageHead
}
}
</script>
From my AddLoad.vue file:
<template>
<div class="add-load">
<div class="content-container container-slim">
<progress-steps/>
<router-link to="#stops">Stops</router-link>
<router-view></router-view>
</div>
</div>
</template>
<script>
import ProgressSteps from '#/components/ProgressSteps'
export default {
name: 'AddLoad',
component: ProgressSteps
}
</script>
Here is a link to a codesandbox, so you can see the full functionality. https://codesandbox.io/s/7k520xk0yq