I Just want to have dynamic tailwind classes values that changes when change a data value, it is possible to do it using tailwind?
In my example I have a double side menus and a main content, I want to set the menus width and programmatically change the margins that have the main content.
I don't know why but tailwind doesn't apply my crafted classes even if in the browser shows the right class in the div element.
Left side menu:
(right is equal)
<nav
class="fixed overflow-x-scroll bg-gray-700 top-16 h-screen"
:class="classes.leftSidebar"
>
<h1 class="text-xl text-center font-bold pt-5">Menu</h1>
<ul class="list-none text-white text-center">
<li class="my-8">
Teams
</li>
<li class="my-8">
Projects
</li>
<li class="my-8">
Favourites
</li>
<li class="my-8">
Notifications
</li>
<li class="my-8">
Members
</li>
</ul>
</nav>
Content:
<main :class="classes.main">
<slot></slot>
</main>
Script:
data() {
return {
showingNavigationDropdown: false,
sidebar_left_w: 64,
sidebar_right_w: 64,
}
},
computed: {
classes() {
return {
leftSidebar: `w-[${this.sidebar_left_w}rem]`,
rightSidebar: `w-[${this.sidebar_right_w}rem]`,
main: [`mr-[${this.sidebar_right_w}rem]`, `ml-[${this.sidebar_left_w}rem]`],
}
}
},
I also tried leftSidebar: `w-${this.sidebar_left_w}`, but same results
This is not possible with Tailwind CSS
The most important implication of how Tailwind extracts class names is that it will only find classes that exist as complete unbroken strings in your source files.
If you use string interpolation or concatenate partial class names together, Tailwind will not find them and therefore will not generate the corresponding CSS:
Don't construct class names dynamically
<div class="text-{{ error ? 'red' : 'green' }}-600"></div>
<!-- This will not work -->
In the example above, the strings text-red-600 and text-green-600 do not exist, so Tailwind will not generate those classes.
Instead, make sure any class names you’re using exist in full:
Always use complete class names
<div class="{{ error ? 'text-red-600' : 'text-green-600' }}"></div>
As long as you always use complete class names in your code, Tailwind will generate all of your CSS perfectly every time.
source
Related
I have a .vue file where I want to use inline styles
<img src="~static/img/info/production/pic4.jpg" class="t22" />
First text
<div class="hr t24"></div>
<h2 class="t25">Second text</h2>
<ul class="services">
<li :style="{ backgroundImage: `url('~static/img/info/production/pic5.jpg')` }" class="sq">
<div class="n">Third text</div>
</li>
</ul>
The image using tag <img> is displayed correctly, but background-image in tag <li> is not.
How do I specify the file path correctly?
EDIT: really did not expect to have to host this one but here it is: https://codesandbox.io/s/so-nuxt-background-image-bf0ly?file=/pages/index.vue
Exact structure, same (ESlinted) template, working solution. Cannot help beyond this point.
I'm not sure that it is the universal solution, but this one is working on my side
<li :style="{ backgroundImage: `url(${require('#/static/japan.jpg')})` }">
The require seems to be required here, not sure why but it works. More in the docs: https://nuxtjs.org/docs/2.x/directory-structure/assets/#images
I started learning vue yesterday and I'm now fiddling around on the CLI3.
Currently I'm trying out the different approaches to inserting data into my markup.
Here, I basically want to make a "list of Lists".
This here is list1:
<template>
<div>
<ul v-for="item in items">
<li :text="item"></li>
</ul>
</div>
</template>
<script>
export default{
name:"list1",
data() {
return {
items: {
item1 : "itemA",
item2 : "itemB",
item3 : "itemC"
}
}
}
}
</script>
This is the list of lists:
<template>
<div>
<h1>All my stuff in a biiig list!</h1>
<listOfLists />
</div>
</template>
<script>
import listOfLists from '#/components/listOfLists.vue'
export default {
name: 'myComplexView.vue',
components: {
listOfLists
}
}
And this is inserted into myComplexView.vue inside views (im working with routing as well, though it doesnt work perfectly yet as you will see on the screenshot), which you can see here:
<template>
<div>
<h1>All my stuff in a biiig list!</h1>
<listOfLists />
</div>
</template>
<script>
import listOfLists from '#/components/listOfLists.vue'
export default {
name: 'myComplexView.vue',
components: {
listOfLists
}
}
</script>
This is the result Im getting:
https://imgur.com/H8BaR2X
Since routing doesnt work correctly yet, I had to enter the url into the browser manually. Fortunately, the site at least loaded that way as well, so I can tackle these problems bit by bit ^^
As you can see, the data was iterated over correctly by the v-for.
However, the data wasn't inserted in the text attribute of the li elements.
I'm a bit clueless about the cause though.
Maybe I'm not binding to the correct attribute? Vue is using its own naming conventions, based off standard html and jquery as far as I understood.
You've got this in your template:
<li :text="item"></li>
This will bind the text attribute to the value, outputting, e.g.:
<li text="itemA"></li>
You should be able to see this in the developer tools. In the picture you posted you hadn't expanded the relevant elements so the attributes can't be seen.
I assume what you want is to set the content. For that you'd either use v-text:
<li v-text="item"></li>
or more likely:
<li>{{ item }}</li>
Either of these will output:
<li>itemA</li>
On an unrelated note, I would add that this line will create multiple lists:
<ul v-for="item in items">
It's unclear if that's what you want. You're going to create 3 <ul> elements, each with a single <li> child. If you want to create a single <ul> then move the v-for onto the <li>.
So, I want to create a navbar and rather than re-invent the wheel, I am using some public code to speed up my MVP dev.
Essentially, I am using this nav-bar code - https://codepen.io/PaulVanO/pen/GgGeyE.
But I am not sure of how I can implement jquery part within my Vue code (I have made a component, copied over html and css, now just need to integrate the jquery functionality within it.)
Here is the Jquery code I need to integrate.
$('#toggle').click(function() {
$(this).toggleClass('active');
$('#overlay').toggleClass('open');
});
It would be really thankful if anyone could help me accomplish with this.
Assuming you have your markup (html and css) as part of one component, getting the toggle to add/remove a class would be really simple, you just need to have a method toggle the active state and a data property to keep the data. An example would be better, so here it goes.
In your component object:
{
data() {
return {
isActive: false
}
},
methods: {
toggleMenu(){
this.isActive = !this.isActive
}
}
}
In your markup you need this
<div class="button_container" id="toggle" :class="{'active': isActive}" #click="toggleMenu">
<span class="top"></span>
<span class="middle"></span>
<span class="bottom"></span>
</div>
------------------------------------
<div class="overlay" id="overlay" :class="{'open': isActive}">
<nav class="overlay-menu">
<ul>
<li >Home</li>
<li>About</li>
<li>Work</li>
<li>Contact</li>
</ul>
</nav>
That should get you going, just note i used the shorthand form for v-on and for v-bind
EDIT:
Here's also a link to an updated pen with the whole example
I am trying to test my vuejs component via jest that contains materialize select.
When performing a component test, I get the following error in materialize.js:
TypeError: Cannot set property 'tabIndex' of null at Dropdown._makeDropdownFocusable
How fix this error?
This problem can happen when the input field is not wrapped inside a div with the class input-field:
<div class="input-field">
<input type="text" class="autocomplete"></input>
</div>
Adding a div with the class "input-field might solve this problem.
use id selector instead class selector. for example call dropdown like this :
html :
<a class='dropdown-trigger' id="dropdowner" href='#' data-target='dropdown1'>Drop Me!</a>
<!-- Dropdown Structure -->
<ul id='dropdown1' class='dropdown-content'>
<li>one</li>
<li>two</li>
<li class="divider" tabindex="-1"></li>
<li>three</li>
<li><i class="material-icons">view_module</i>four</li>
<li><i class="material-icons">cloud</i>five</li>
</ul>
js:
$('#dropdowner').dropdown();
Can only be used once.
data-target="name_target" must not be repeated
Exam1.❌
<nav>
<div class="nav-wrapper">
<ul class="right hide-on-med-and-down">
<li><a class="dropdown-trigger" href="#!" data-target="name_target1">Dropdown<i class="material-icons right">arrow_drop_down</i></a></li>
<li><a class="dropdown-trigger" href="#!" data-target="name_target1">Dropdown<i class="material-icons right">arrow_drop_down</i></a></li>
</ul>
</div>
</nav>
<!-- Dropdown Structure -->
<ul id="name_target1" class="dropdown-content">
<li>one</li>
<li>two</li>
</ul>
Exam2.✔️
<nav> <div class="nav-wrapper">
Logo
<ul class="right hide-on-med-and-down">
<li><a class="dropdown-trigger" href="#!" data-target="name_target2">Dropdown<i enter code here class="material-icons right">arrow_drop_down</i></a></li>
</ul> </div> </nav> <ul id="name_target2" class="dropdown-content"> <li>one</li> <li>two</li> </ul>
When I ran into this issue I was trying to create the whole dropdown list dynamically in JS. The fix for me was creating the list and any default list elements in HTML:
<div id="select1" class=\"input-field col s12\">
<select>
<option value="" selected>Default</option>
</select>
<label>Test</label>
</div>
Then appending any dynamic values in JS:
contents.forEach(function(content) {
var buffer = "<option></option>";
var template = $(buffer);
$(template).text(content);
$("select1").find("select").append(template);
});
$("select").formSelect();
pre 1.0.0 you would use data-activates, if data-target is not specified you will get this error
My problem was, that jQuery object was not attached to the DOM yet, so inner materialise code could not init element due to inability to find element by ID:
// materializecss initing dropdown (in my case for input autocomplete), where `t` is the input element
i.id = M.getIdFromTrigger(t),
i.dropdownEl = document.getElementById(i.id),
i.$dropdownEl = h(i.dropdownEl),
M.getIdFromTrigger(t) returned some random ID (not the one I provided) and dropdownEl was inited with null, and later method _makeDropdownFocusable failed on using it `this.dropdownEl.tabIndex = 0
So my problem code looked like this:
let root = $('#root'); // root in the DOM already
let wrapper = $('<div>'); // wrapper is just created and NOT attached to the DOM yet
let input = $('<input>').appendTo(wrapper); // creating input and attaching to the wrapper, but still not in DOM
initAutocomplete(input) // M.Autocomplete.init logic here FAILS
root.append(wrapper) // too late, error above
So the quick fix is to append elements first and only than do M.Autocomplete.init
I just stumbled this issue too while using Materializecss for my Vue project. As mentioned by sajjad, using id selector instead of class works. However, this is problem for initializing multiple dropdown, since each dropdown must have unique ID.
The way I solve this is just by selecting all the elements with the '.dropdown-trigger' class, and initialize every each of those. It works for me.
$.each($('.dropdown-trigger'), function(index, value) {
$(value).dropdown();
});
I have this component which is managed by Bootstrap, specifically one of those nav-tabs widgets where, as you click Bootstrap shows and hides.
Bootstrap keeps track of which item was clicked on using the .active class. And, in Vue, I was to initialize a certain nav as being active on page load. But, once that's done, I want Vue leave the .active class management entirely up to Bootstrap.
<template>
<li class="nav-item" v-if="toshow">
<a class="nav-link" v-bind:id="'nav_' + link"
:class="{ active: isActive }" :aria-expanded="isActive"
v-bind:href="'#'+link" data-toggle="tab" #click="onclick">
{{label_}}
<span v-if="badge" class="badge" :class="badge_level">{{badge}}</span>
<span v-if="dynamic_badge" class="badge" :class="badge_level" >{{badge_value}}</span>
</a>
</li>
</template>
At page load time, each component checks against Vuex and figures out if its id is in this.$store.state.active_tab - that's what sets .active.
,isActive: function(){
//active_tab is where I specify which tab should be active
//at first
var res = this.link === this.$store.state.active_tab;
return res;
},
v-once is not a good fit, because the only thing I want to disable is the computation of .active (the badge children need to be updated live).
The component works, kinda. I think mostly because this.$store.state.active_tab's value does not mutate so Vue doesn't re-render. But it seems brittle at best.
What are best practices for using Vue to only set the initial values of certain variables, and then relinquishing control, without using v-once?
I would just access the a.nav-link element and add the .active class to its classList directly.
You can add a ref attribute to the a.nav-lank element link so:
<a class="nav-link" ref="link" ...>
...
</a>
And then add the .active class in the mounted hook:
mounted() {
if (this.link === this.$store.state.active_tab) {
this.$refs.link.classList.add('active');
}
}