Vuetify : Overwrite theme colors - vue.js

I'm trying to overwrite some classes.
src/plugins/vuetify.js
import Vue from "vue"
import Vuetify from "vuetify/lib/framework"
Vue.use(Vuetify)
export default new Vuetify({
theme: {
primary: "#4BB7E8",
info: "#769BD0",
success: "#9B83BC",
warning: "#82C341",
error: "#53BD6D",
default: "#30B795"
}
})
and tried
<v-navigation-drawer v-model="drawer" app class="blue lighten-5">
<p class="success">menu goes here</p>
<p class="info">menu goes here</p>
<p class="primary">menu goes here</p>
<p class="danger">menu goes here</p>
<p class="warning">menu goes here</p>
<p class="default">menu goes here</p>
</v-navigation-drawer>
Result
It's clearly not working because it seems to use default colors.

The correct way to do this is:
export default new Vuetify({
theme: {
themes: {
light: {
primary: "#4BB7E8",
info: "#769BD0",
success: "#9B83BC",
warning: "#82C341",
error: "#53BD6D",
default: "#30B795"
}
}
}
})
[ https://vuetifyjs.com/en/styles/colors/#javascript-color-pack ]

Related

Dynamic import of SVG icon components

I'm trying to import SVG icons for each item in a v-for loop, with the filename changing depending on the item's id. The icons are loading, but I get the following error for each icon imported.
Is there a better way to approach this?
Uncaught (in promise) TypeError: Failed to resolve module specifier '~/assets/img/flags/ar.svg'
<template>
<NavigationItem v-for="item in topCountries">
<template #icon>
<component :is="getIcon(item.id)" />
</template>
<NavigationItem />
</template>
<script setup>
const getIcon = (id) => defineAsyncComponent(() =>
import(`~/assets/img/flags/${id}.svg`));
</script>
You can have a look at https://nuxt.com/modules/nuxt-svgo module.
This module allows to import SVG.
npm i --save nuxt-svgo
Add it as a module dependency in your nuxt.config file
// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'
// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
modules: ['nuxt-svgo']
})
Import SVG icons as follow:
<script setup lang="ts">
const getIcon = (id: string) => defineAsyncComponent(() => import(`#/assets/svg/${id}.svg`));
</script>
<template>
<div v-for="item in ['icon1', 'icon2']">
<component :is="getIcon(item)" />
</div>
</template>
Note that if you use Typescript, you will have to create a custom.d.ts file to fix import error
// custom.d.ts
declare module '*.svg' {
import type { DefineComponent } from 'vue'
const component: DefineComponent
export default component
}
calls each icon from the data. uses font awesome icons. you can also add svgs between the i tags
<template>
<ul>
<!-- list rendering -->
<li v-for="item in items">
<span class="icon">
<i :class="[faClass(item.icon)]"
aria-hidden="true"></i>
</span>
</li>
</ul>
</template>
<script>
export default {
name: "navbarMobile",
data() {
return {
//listItems
items: [
{
icon: 'home',
},
{
icon: 'wrench',
},
{
icon: 'project-diagram',
},
{
icon: 'cogs',
},
{
icon: 'phone',
}
]
}
},
methods: {
faClass(icon) {
return `fa fa-${icon}`;
}
}
}
</script>
Us the component name instead of the component path. Also, don't forget to import SVG components and add ?inline at the end of the name.
<template>
<NavigationItem v-for="item in topCountries">
<template #icon>
<component :is="item.icon" />
</template>
<NavigationItem />
</template>
<script setup>
import Eye from '~/assets/img/flags/Eye.svg?inline';
import Balls from '~/assets/img/flags/Balls.svg?inline';
const topCountries = [
{ icon: 'Eye' },
{ icon: 'Balls' }
]
</script>

CKEditorError: ckeditor-duplicated-modules while adding plugins to ckeditor

I'm trying to add text-alignment plugin to my ckeditor build in vue js.
Following is my code for the same::
<template>
<div>
<nav-bar />
<div id="app">
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig" class="full-width"></ckeditor>
</div>
<router-view class="fixed-center"></router-view>
</div>
</template>
<script>
import NavBar from "components/NavBar.vue";
import ClassicEditor from "#ckeditor/ckeditor5-build-classic"
import Alignment from "#ckeditor/ckeditor5-alignment"
export default {
components: { NavBar },
name: "app",
data() {
return {
editor:ClassicEditor,
editorData:'<p>Content of the editor.</p>',
editorConfig:{
plugins:[Alignment],
toolbar:['Heading','bold', 'italic','alignment']
}
};
},
methods: {},
};
</script>
I'm getting following error ::
CKEditorError: ckeditor-duplicated-modules

Vuetify theme is being ignored

I have created a file in my plugins directory which looks like this:
import Vue from "vue";
import Vuetify from "vuetify/lib/framework";
Vue.use(Vuetify);
export default new Vuetify({
theme: {
themes: {
light: {
primary: "#081d4d", // $blue
secondary: "#00c8b7", // $jade
//anchor: "#081d4d", // $blue (by default vuetify styles anchors with the same colour of primary)
accent: "#82B1FF", // $blue
error: "#ff4438", // $warm-red
info: "#835dd0", // $violet
success: "#4CAF50", // none
warning: "#ff8204", // $orange
},
},
},
});
And then I use it in my main.ts like this:
import "./registerServiceWorker";
import Vue from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import { provide } from "#vue/composition-api";
import { DefaultApolloClient } from "#vue/apollo-composable";
import "./plugins/axios";
import vuetify from "./plugins/vuetify";
import apolloClient from "./plugins/vue-apollo";
Vue.config.productionTip = false;
new Vue({
router,
store,
vuetify,
setup() {
provide(DefaultApolloClient, apolloClient);
},
render: (h) => h(App),
}).$mount("#app");
When I use a button or alert and set their colours, it's not using my theme.
Also, even if I try to change to the dark theme, nothing happens.
This is the template:
<template>
<div class="container-fluid d-flex align-items-center justify-content-center">
<div class="row">
<div class="col">
<div class="section section-white">
<h1>This is a test</h1>
<p>With some tests content</p>
<v-btn color="primary">Test</v-btn>
<v-alert type="info"></v-alert>
</div>
</div>
</div>
</div>
</template>
This is what my UI looks like:
As far as I can tell, I have followed the directions correctly, so I have no idea why this is not working.
Try to change this from
import Vuetify from "vuetify/lib/framework";
to
import Vuetify from "vuetify/lib";
Moreover, if you are not able to use theme attributes directly use it like this.
<v-btn :color="$vuetify.theme.themes["light"].primary">Test</v-btn>
or you can also use computed property for that
computedPrimaryColor(){
return this.$vuetify.theme.themes["light"].primary;
}
and use it like
<v-btn color="computedPrimaryColor">Test</v-btn>

Vue2-leaflet map not showing properly in BoostrapVue modal

Here's my problem - a Vue2 leaflet map does not render correctly in BootstrapVue modal.
Here's what it looks like visually (it should show just the ocean)
<template>
<div>
<b-modal size="lg" :visible="visible" #hidden="$emit('clear')" title="Event details">
<div class="foobar1">
<l-map :center="center" :zoom="13" ref="mymap">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="center"></l-marker>
</l-map>
</div>
<template slot="modal-footer">
<b-btn variant="danger" #click="deleteEventLocal(event.id)">Delete</b-btn>
</template>
</b-modal>
</div>
</template>
<script>
import * as moment from "moment";
import { LMap, LMarker, LTileLayer } from "vue2-leaflet";
import { deleteEvent } from "./api";
import "vue-weather-widget/dist/css/vue-weather-widget.css";
import VueWeatherWidget from "vue-weather-widget";
export default {
data() {
return {
center: L.latLng(event.latitude, event.longitude),
url: "http://{s}.tile.osm.org/{z}/{x}/{y}.png",
attribution:
'© OpenStreetMap contributors'
};
},
props: {
visible: {
type: Boolean
},
event: {
required: true,
type: Object
}
},
methods: {
async deleteEventLocal(id) {
await deleteEvent(id);
this.$emit("refresh");
this.$emit("clear");
}
},
components: {
weather: VueWeatherWidget,
LMap,
LMarker,
LTileLayer
}
};
</script>
As you can see there aren't any CSS rules that could make the map spill outside the modal as it does. Which is weird.
I'm kinda asking this question to answer it myself as I couldn't find a solution before.
There were 3 issues because of which this was happening.
1. First - I forgot to load the leaflet css into main.js - this is why the leaflet map was somehow outside the modal.
//src/main.js
import '#babel/polyfill';
import Vue from 'vue';
import './plugins/bootstrap-vue';
import App from './App.vue';
import router from './router';
import store from './store';
//above imports not important to this answer
import 'leaflet/dist/leaflet.css'; //<--------------add this line
new Vue({
router,
store,
render: h => h(App),
}).$mount('#app');
2. Now the map may disappear. Set a width and height on the l-map component's container. I used a class but you can use style="" etc.
<div class="foobar1"> <!-- <--- Add a class on l-map's container -->
<l-map :center="center" :zoom="13">
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="center"></l-marker>
</l-map>
</div>
<style lang="scss">
.foobar1 { /* <--- class we added above */
width: 100%;
height: 400px;
}
</style>
3. Now your map will render within the modal but if you move the map's view, you'll see that leaflet does not download the map's squares in time.
You will see something like this:
To fix this:
create an event handler on b-modal for the #shown event.
<b-modal
#shown="modalShown"
#hidden="$emit('clear')"
size="lg"
:visible="visible"
title="Event details"
>
I called mine modalShown.
Then, add a ref attribute to your l-map. I called mine mymap.
<l-map :center="center" :zoom="13" ref="mymap"> <!-- ref attribute added to l-map -->
<l-tile-layer :url="url" :attribution="attribution"></l-tile-layer>
<l-marker :lat-lng="center"></l-marker>
</l-map>
Then, create a modalShown method in the Vue methods for your view/component and call invalidateSize() inside.
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
//mapObject is a property that is part of leaflet
this.$refs.mymap.mapObject.invalidateSize();
}, 100);
}
}
}
Now everything should be fine:
map should not spill outside the modal
map should be visible (duh)
map squares should be downloaded when within map body
Here's my full code, it contains some stuff specific to my app but overall it contains all of the code snippets above.
Addtional to Artur Tagisow answer
You can also use this approach to your parent component if your map is in child component.
export default {
data() {
//some data here
}
methods: {
modalShown() {
setTimeout(() => {
window.dispatchEvent(new Event("resize"));
}, 100);
}
}
}
For vue.js and nuxt.js developers , probably it's because of using v-show or v-if
!in your case display none happening by bootstrap modal
but dont worry the only thing u have to do is using client-only (its like ssr but for new version of js frameworks like nuxt or vue):
<client-only>
<div id="bootstrapModal">
<div id="map-wrap" style="height: 100vh">
<l-map :zoom=13 :center="[55.9464418,8.1277591]">
<l-tile-layer url="http://{s}.tile.osm.org/{z}/{x}/{y}.png"></l-tile-layer>
<l-marker :lat-lng="[55.9464418,8.1277591]"></l-marker>
</l-map>
</div>
</div>
</client-only>
ps: if still not loaded in iphone browsers it's probably because of geolocation

Can't change router component

I have a .vue file with the following
<template>
<div class="container">
<div class="row">
<div class="column">
<h2>Create your MIA</h2>
<p><img src="../../static/intro.gif"/></p>
<p><a v-on:click="go()" href="javascript:void(0)" class="button">Enter</a></p>
</div>
</div>
</div>
</template>
<script>
export default {
methods: {
go: function () {
console.log(this.$router.go)
this.$router.go({ path: '/app' })
}
}
}
</script>
and in a main index.html file I have
<main class="container center">
<div id="logo"></div>
<div id="section">
<router-view></router-view>
</div>
</main>
and in my main.js
import Vue from 'vue'
import Resource from 'vue-resource'
import Router from 'vue-router'
import App from './components/app'
import Intro from './components/intro'
Vue.use(Resource)
Vue.use(Router)
const route = new Router({hashbang: false,
history: true,
linkActiveClass: 'active',
mode: 'html5'})
// Pointing routes to the components they should use
route.map({
'/': {
component: Intro,
subRoutes: {
'app': {
component: App
}
}
},
'/app': {
component: App
}
})
// Any invalid route will redirect to home
route.redirect({
'*': '/app'
})
route.start(Intro, '#section')
When the stuff is compiled I am able to get the Intro component but click on the button only changes the hash but not the component....
Based on the documentation the only thing that I'm doing different is that I am changing the route programmatically.
What am I doing wrong here?