Summarize the problem
I am trying to implement the Vuetify to a part of an existing project. But after I added Vuetify to the Project. I found out that the "default" CSS styles for like input field, select are changed. And it makes those input field and select all look like plain text rather than input field and select.
Because I only want to implement the Vuetify for a part of the project, so it is bad that the Vuetify overrides the "default" CSS Rules.
I am looking for a way to implement the Vuetify for a part of an existing project. But the rest of the project should be rendered as normal (just with default CSS, not my own CSS).
To make the Qustion more clair, I will put an example which shows two selects. The first one is made with Vuetify <v-select> and the second one is made with normal HTML code <select>
Provide background and tell us what you've already tried
I have already tried to put custom CSS rules for input field and select after the Vuetify Script and Vuetify CSS link. But Vuetify still overrides my custom CSS-Styles.
Show your code
HTML PART:
<div id="app">
<div>Vuetify select:</div>
<v-select
:items="items"
>
</v-select>
<hr/>
<div>
<div>Normal select:</div>
<select>
<option value="0">test1</option>
<option value="1">test2</option>
<option value="2">test3</option>
</select>
</div>
</div>
JS PART:
new Vue({
el: '#app',
data() {
return {
item: null,
items: [
{
text: "a"
},
{
text: "b"
},
{
text: "c"
},
]
}
}
})
Describe expected and actual results
I expected that I can use Vuetify for some parts of this project. But in the meanwhile, the rest of the project should be acting just like normal (with default CSS).
This is caused by the Vuetify reset styles (src/styles/generic/_reset.scss).
There is also an issue for that problem: https://github.com/vuetifyjs/vuetify/issues/8530. You can find there a little postcss hack from mkalus that isolates necessary styles via the wrapper (adding the prefix class to selectors).
In my case I just needed to remove some element selectors, excluding those that I added myself. So this is my variation of mkalus's solution with the postcss-filter-rules plugin.
I used the filter option to filter selectors. Its description:
Selectors are kept if the function returns true, otherwise they are removed.
And the keepAtRules option to prevent unnecessary deletions:
By default, #font-face and any empty at-rules (after filtering) are removed. To keep specific at-rules, provide an array of names to this option. To keep all at-rules, use the value true.
vue.config.js (Vue CLI 4):
const autoprefixer = require('autoprefixer')
const filterRules = require('postcss-filter-rules')
module.exports = {
/* ... */
css: {
loaderOptions: {
postcss: {
plugins: [
filterRules({
filter: (selector) => {
const re = new RegExp(/^(html|body|\*|ul|ol|select|small)(\W|$)/, 'i')
const exception = '.vue-global'
return !re.test(selector) || selector.includes(exception)
},
keepAtRules: true
}),
autoprefixer
]
}
}
}
/* ... */
}
Now that I've removed some Vuetify reset styles, I can still style html and other elements like this:
html.vue-global
font-size 16px
You can try adding a normalize css file to your project and the vuetify styling should only apply to when you want it to, i use this
Related
I use HTML editor material ui :
import MUIEditor, { MUIEditorState } from "react-mui-draft-wysiwyg";
<MUIEditor
editorState={formElement.editorState}
onChange={formElement.onChange}
/>
I want to remove the font color button in the toolbar. When I go to the MUIEditor file at node-modules and I want to make some changes to that file but it does not seem to change even when I get a console I can not see the result. What should I do?
.node_modules
.react-mui-draft-wysiwyg
.dist
.index.js
It is rarely advisable to edit the contents of /node_modules -- instead react-mui-draft-wysiwyg provides direct a way to customize the toolbar configuration through the config prop, in your own React code.
In your case, to hide the font color button, you simply need to pass in the menu options that you would like to display. (ie. remove/comment out the toolbarControlTypes.fontColor option). For example:
import MUIEditor, {
MUIEditorState,
toolbarControlTypes // Added toolbarControlTypes
} from "react-mui-draft-wysiwyg";
...
<MUIEditor
editorState={editorState}
onChange={onChange}
config={{
toolbar: {
controls: [
toolbarControlTypes.undo,
toolbarControlTypes.redo,
toolbarControlTypes.divider,
toolbarControlTypes.bold,
toolbarControlTypes.italic,
toolbarControlTypes.underline,
toolbarControlTypes.strikethrough,
// Include all of the default toolbar options except for fontColor
// toolbarControlTypes.fontColor,
toolbarControlTypes.fontBackgroundColor,
toolbarControlTypes.divider,
toolbarControlTypes.linkAdd,
toolbarControlTypes.linkRemove,
toolbarControlTypes.image,
toolbarControlTypes.divider,
toolbarControlTypes.blockType,
toolbarControlTypes.fontSize,
toolbarControlTypes.fontFamily,
toolbarControlTypes.textAlign,
toolbarControlTypes.divider,
toolbarControlTypes.unorderedList,
toolbarControlTypes.orderedList
]
}
}}
/>
Documentation: Default Configuration Options
Working CodeSandbox: https://codesandbox.io/s/mui4-draft-wysiwyg-bre8e?file=/demo.js
I'm trying to figure out how to set up Vue-multiselect component on Laravel 5. Until now i've got a component called register.vue
and here is the part of the code where i need the component (I won't put all the code here becase it'd be too large.
<b-row align-v="center">
<multiselect
v-model="selected"
:options="options">
</multiselect>
</b-row>
Here's where i included the component in the script section
import Multiselect from 'vue-multiselect';
export default {
components: { Multiselect },
data(){
return {
selected: null,
options: ['list', 'of', 'options'],
}
}
Nevertheless, what i'm obtaining is a weird component like this one
This is how it looks when the focus is not in the component
And when the focus is in the component it only shows an input field with some bullet list which the elemtents of the array with the options are.
Does somebody know what is going on in my app? I've been a lot of time checking if there's some missed css file or stuff like that but everything seems to be OK, except that part, my component seems not be loading any style.
Thanks a lot everyone.
I noticed you included the b-row part which lets me know you have Bootstrap Vue, considering you have that whole library and all of it's CSS included (it may even contain a multiselect component of its own or use select2). It's most likely that the two stylesheets are messing with each other or one is causing the other not to init correctly or at the proper time.
I found this issue here which seems possibly like it could help you withchecking your styling. https://github.com/shentao/vue-multiselect/issues/718
Also I would get rid of all the other Vue components off that page for a minute and load in Vue Multiselect by itself exactly according to their documentation. That will let you narrow it down to the problem being a conflict between another Vue component or Laravel / when you are starting up Vue multiselect.
I use it in a PHP / Vue project currently this is my working setup with Buefy framework.
I made my own Vue component as a wrapper for multiselect which lets me scope the CSS to just its specific HTML.
<template>
<multiselect
v-model="value"
:options="options"
:placeholder="placeholder"
label="label"
track-by="value"
#input="inputChanged" />
</template>
<script>
import Multiselect from 'vue-multiselect';
export default {
components: { Multiselect },
props: {
options: {
type: [Array],
default() {
return [];
}
},
savedValue: {
type: [Array],
default() {
return [];
}
},
placeholder: {
type: [String],
default: 'Select Option...'
}
},
data() {
return {
value: null
};
},
mounted() {
this.value = this.savedValue;
},
methods: {
inputChanged(selected) {
this.$emit('selected', selected.value);
}
}
};
</script>
<style scoped>
#import '../../../../../node_modules/vue-multiselect/dist/vue-multiselect.min.css';
</style>
Then you can call the component from another file kind of like this.
<select-input
:saved-value="artistSelected"
:options="artistOptions"
:placeholder="'Choose an existing artist...'"
#selected="artistChanged"
/>
Scoping the CSS like I did will help other things from not messing with your styling.
The problem occurs because of the wrong component import statement.
In my case, the following statement gave the correct behaviour:
import Multiselect from 'vue-multiselect/src/Multiselect'
I am using the Redactor editor as part of Perch. I would like to give the editor the ability to (optionally) add the class of "button" to any <a> tag they add. This could be via an additional option in the existing Add a Link modal, or could be a separate button in the editor toolbar.
Does anyone have any guidance as to the best way to achieve this? Any pointers appreciated.
This is my current config setup:
config.plugins = [];
config.buttons = ['format','bold','italic','deleted','link','lists'];
config.formatting = ['p', 'blockquote', 'h2', 'h3', 'h4'];
You can use formattingAdd to create a custom set of formatting options for Formatting dropdown. This will allow you to add your own CSS classes.
formattingAdd: {
'red-p-add': {
title: 'Red Paragraph',
api: 'module.block.format',
args: {
tag: 'p',
class: 'red-styled',
},
},
}
Unfortunately, according to the Official Documentation:
formattingAdd can only be applied to block tags (p, pre, blockquote, div, heading, etc).
In other words, since <a> is an inline element (not a block element), if you are trying to create an option using built-in Redactor functionality, then it appears you are out of luck.
As noted in other answers, formattingAdd can not be applied to a tags. Here's a plugin for the latest version of redactor that takes highlighted text/links and converts it into an a tag with a specific class you're after:
(function($R) {
$R.add('plugin', 'button', {
init: function(app) {
this.app = app;
},
activate: function() {
// Remove existing link if any
this.app.api('module.link.unlink')
// Add a tag with 'button' class
this.app.inline.format({ tag: 'a', class: 'button' })
}
});
})(Redactor);
With that code defined and loaded, you then need some updates to the redactor json config to pull in the functionality:
// include the plugin to redactor's world
"plugins": ["button"],
...
"formattingAdd": [
...
// add a "Button" option in the formatting dropdown,
// but use it to trigger your own plugin's function
{
"api": "plugin.button.activate",
"args": {
"class": "button",
"tag": "a"
},
"title": "Button"
},
]
I attempted to throw a this.app.api('module.link.open') as the last line of the activate function, so the link modal would be opened up as soon as your link class was activated. It was nice, but I noticed some inconsistent behavior depending on the scope of the initial selection (worked well if just the text was selected, but if a DOM tag portion was also selected the whole thing broked).
I'm not too familiar with Redactor, but perhaps you could you do it with a callback or pure JavaScript after the element loads.
<style>
.my-custom-class-1 {
background-color: red;
}
.my-custom-class-2 {
font-size: 16px;
}
.my-custom-class-3 {
font-family: Helvetica Neue, Helvetica, Arial;
}
</style>
Not sure what is returned from link but if it the html element you may be able to add classes with a callback.
$R('#content', {
callbacks: {
link: {
inserted: function(link) {
// use the classList API to remove and add classes
link.classList.remove("my-custom-class-1");
link.classList.add("my-custom-class-1");
// add or remove multiple classes
link.classList.add("my-custom-class-1", "my-custom-class-2", "my-custom-class-3");
link.classList.remove("my-custom-class-1", "my-custom-class-2", "my-custom-class-3");
}
}
}
});
If the links have a custom id then you may be able to do this in pure JavaScript
const link_1 = document.getElementById('linkId_1');
const link_2 = document.getElementById('linkId_2');
const link_3 = document.getElementById('linkId_3');
// use the classList API to remove and add classes
link_1.classList.remove("my-custom-class-1");
link_1.classList.add("my-custom-class-1");
// add or remove multiple classes
link_1.classList.add("my-custom-class-1", "my-custom-class-2", "my-custom-class-3");
link_1.classList.remove("my-custom-class-1", "my-custom-class-2", "my-custom-class-3");
Hope this helps! :)
I know this is a bit of an old question, but I got tired of coming across the same half-baked solutions in every old thread I came across.
I wrote a plugin that lets you configure a list of class names that content editors can choose from when adding / editing a link.
It works seamlessly in combination with the default Redactor link module.
https://github.com/simplicate-web/redactor-link-styles
I am able to register a custom vue.js component with
// register
Vue.component('my-component', {
template: '<div class="my-class">A custom component!</div>'
})
Also see https://v2.vuejs.org/v2/guide/components.html
How can I include css classes for my component?
I would expect something like
Vue.component('my-component', {
template: '<div class="my-class">A custom component!</div>',
css: '#... my css stylesheet...'
})
but there does not seem to be a css option.
I know that I could
a) define all css classes in a global css stylesheet or
b) use singe-file-vue-components (would require build tool supporing *.vue files, see https://v2.vuejs.org/v2/guide/single-file-components.html)
but I would prefer to
c) specify a css stylesheet for the component when registering the component.
=> How to do so?
there does not seem to be a css option.
That is correct. You cannot do what you describe. The documentation on single file components is pretty clear that one of the advantages is that you can do this with them and cannot do it without them.
In many Vue projects, global components will be defined using
Vue.component, followed by new Vue({ el: '#container' }) to target a
container element in the body of every page.
This can work very well for small to medium-sized projects, where
JavaScript is only used to enhance certain views. In more complex
projects however, or when your frontend is entirely driven by
JavaScript, these disadvantages become apparent:
[...]
No CSS support means that while HTML and JavaScript are
modularized into components, CSS is conspicuously left out
Here is a way to achieve what you're looking for:
export const ContactUs = Vue.component(
'mycomponent-contact-us'
,{
props: {
backgroundColor: {
type: String
,required: false
,default: "red"
}
}
,data: function(){
return {
}
}
,template: `
<div>
<span class='contact_us_text' >Contact Us Component and its bg color will be {{backgroundColor}}</span>
</div>
`
,mounted: function(){
var css_text = `
.contact_us_text{
color: `+this.backgroundColor+`;
}
`;
var css = document.createElement('style');
css.type='text/css';
css.setAttributeNode( document.createAttribute('scopped') );
css.appendChild( document.createTextNode( css_text ) );
this.$el.appendChild( css );
}
}
);
Its true that you cannot add <style> inside a Vue template or add CSS within
component directly, unless you bind it or define your css globally. But you can create a custom component that will dynamically do it for you. sample
Keep in mind that Vue components are effectively macros.
Where render is the substitution function, and the vueDefinition (defn3 below) is effectively a class for the given tagName.
A template is just a convenient syntactic-sugar shorthand that will be compiled (with some vue-usage pattern restrictions) into a render function if you don't provide your own render function.
const defn3 = {
tagName: 'ae-css',
mounted() {
const vueDefinition = this.$options;
this.$el.appendChild(document.createTextNode(vueDefinition.css));
},
css: `
* {
color: blue;
}
`,
render(h) {
return h('style');
}
}
Vue.component(defn3.tagName, defn3);
With that solution in hand, there are a number of good reasons why you probably don't want something as simplistic as what I just provided.
Namely, you want to have your css modularized such that it does not affect any aspects of your page you did not intend it to. For that, you either need carefully designed css rules with your intended inheritance and scope; probably using a class=... But a better approach would be to just use Vue's facilities that offer similar capabilities automatically.
If you want to use modern browser architecture capabilities for this, then you might want your components to be real browser DOM WebComponents that make use of the shadowDOM and keep your internal elements and styles encapsulated within a shadowRoot. See this library, for doing that in Vue.
You can embed a style tag within your template root element:
Vue.component('my-component', {
template: `
<div class="my-class" my-component>
A custom component!
<style>
.my-class[my-component] {
// ... my-component styles
}
</style>
</div>
`
})
Try this:
this.$el.style.cssText = "border: 5px solid blue;"
I'm new to Vue and trying to implement Jsignature within a 'custom' Vuejs component.
My solution is based on: https://v2.vuejs.org/v2/examples/select2.html
It should be straight forward however I don't get it working, the solution I got so far results in the following error:
'Jsignature' is defined but never used
import Jsignature from '../../lib/jsignature
The component containing the signature.
<template>
<div>
<app-signature></app-signature>
</div>
</template>
<script>
import Signature from './signature/Signature.vue'
export default {
components: {
appSignature: Signature
}
}
</script>
The signature component.
<template>
<div id="signaturecanvas"></div>
</template>
<script>
import Jsignature from '../../lib/jsignature'
export default {
data () {
return {
signature: ''
}
},
methods: {
initial () {
var element = ('#signaturecanvas')
element.Jsignature.jSignature()
}
},
created () {
this.initial()
}
}
</script>
<style></style>
Never worked with Jsignature but I suppose you use it as a jquery plugin.
The issue you have is right at the this.$signaturecanvas. This is somehow a wrong way to get the div via jQuery.
var element = ("#signaturecanvas") or var element = $(this.$el) if you want to selected the whole component. $el refers to the identifier of the current vue component instance and basically is the first tag from the component. Choose the appropriate way depending on what you want to select and you should get it working.
Instead of importing JQuery and JSignature, I made the choice to use signature pad. https://github.com/szimek/signature_pad
This 'plug-in' is in native javascript/html5 which makes my application less constraint to external libraries like JQuery.