Vue Single File Component binding data-v-xxxxxxxx to generated elements - html

I'm building a Vue component as a Single File Component:
<template>
<div class="chart"></div>
</template>
<script>
import * as d3 from 'd3';
export default {
data() {
return {
data: [4, 8, 15, 16, 23, 42],
};
},
mounted() {
d3.select('.chart')
.selectAll('div')
.data(this.data)
.enter()
.append('div')
.style('width', d => `${10 * d}px`)
.text(d => d);
},
};
</script>
<style lang="scss" scoped>
.chart {
div {
background-color: steelblue;
color: white;
font: 10px sans-serif;
margin: 1px;
padding: 3px;
text-align: right;
}
}
</style>
After processing with webpack, the CSS is rendered like so:
<style type="text/css">
.chart div[data-v-xxxxxxxx] {
background-color: steelblue;
color: white;
font: 10px sans-serif;
margin: 1px;
padding: 3px;
text-align: right;
}
</style>
But the HTML shows up as:
<div data-v-xxxxxxxx class="chart">
<div style="width: 40px;">4</div>
<div style="width: 80px;">8</div>
<div style="width: 150px;">15</div>
<div style="width: 160px;">16</div>
<div style="width: 230px;">23</div>
<div style="width: 420px;">42</div>
</div>
I'm using D3 to generate the child <div>s. I've found that data-v-xxxxxxxx isn't bound to generated elements. If I include the child <div>s in the original template rather than generating them, they each have the data-v-xxxxxxxx attribute and the styles apply as expected
I would think that any descendant of the root node, whether included in the template or generated, should be bound to the rules of the scoped CSS. Is there any way to force this?

New version of vue-loader (from version 12.2.0) allows you to use "deep scoped" css. You need to use it that way:
<style scoped> now support "deep" selectors that can affect child
components using the >>> combinator:
.foo >>> .bar { color: red; } will be compiled into:
.foo[data-v-xxxxxxx] .bar { color: red; }
More informations on the release page of vue-loader

Related

Using v-for to get unique ID of elements and access specific IDs in CSS

I am trying to identify each element of a v-for directive with a unique ID, so I can access the HTML object with the ID and change its CSS.
Currently, this is my HTML with Vue.
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script type="text/javascript" src="assets/js/vue#2.6.12/dist/vue.js"></script>
<title>remoteProto</title>
<style type="text/css">
html,
.switch {
white-space: nowrap;
display: inline-block;
padding: 30px;
background-color: rgb(255, 223, 223);
background-repeat: no-repeat;
background-size: 100%;
position: relative;
top: 24px;
right: 194px;
transform: rotate(0deg);
}
.switch.closed {
background-image: url(assets/image/switch-closed.svg);
background-position: 0px 0px;
}
.switch.opened {
background-image: url(assets/image/switch-opened.svg);
background-position: 0px -7.5px;
}
</style>
</head>
<div id="app">
<fieldset style="background-color: rgb(181, 207, 209);">
<h1>simTest server</h1>
<hr>
<div class="circuitplan">
<div v-for="(val, key) in switchObj" v-bind:key="key">
<div>{{ key }}
<span class="switch" v-bind:class="{ closed: val==='closed', opened: val==='opened' }" #click="onSwitchClick(key)" ></span>
</div>
</div>
</div>
</fieldset>
</div>
<script>
const app = new Vue({
el: '#app',
data () {
return {
ws: null,
idCount: 1,
url: 'ws://localhost:3000',
switchObj: {
/*'K1': 'opened',
'K2': 'opened',
'K3': 'opened'
*/
},
sentObj: {},
}
},
})
</script>
</html>
How can I change the CSS of this specific ID?
Let's say "key" is named the following: "K1", "K2", "K3", ...
The class is "switch".
I know this is not right but to illustrate what I mean, I would like to have something like this:
switch.K1 {other position than e.g. K2}
switch.K2 {...}
Also, the switch is bound to close and opened, see the CSS.
I guess my syntax of the HTML reveals me being a noob. Anyway, I hope you guys can help me, thank you!
You have two choices :
1- defining an unique for each element then define its style like :
K1{
...
}
K2{
...
}
...
Kn{
...
}
template (key represents KEY1 KEY2 ...):
<div v-for="(val, key,index) in switchObj" v-bind:id="key">
2- to define a data property that contains the style of each element and bind it the element using the key:
url: 'ws://localhost:3000',
style:{
K1:{
color:'red'
},
K2:{
color:'geen'
}
}
in template use inline style binding :
<div v-for="(val, key,index) in switchObj" v-bind:style="style[key]">

How to animate the height of a box depending to the content inside?

It should be simple, but I can't find how.
In this exemple, when adding or removing a new item, i would like to the the #app height change smoothly, instead of instantanly.
In pure css
Thanks for help.
https://codesandbox.io/s/sparkling-frog-qfy64
<template>
<div id="app">
<button #click="addItem">Add</button>
<button #click="removeItem">Remove</button>
<div v-for="(item, i) in items" class="box" :key="i">BOX</div>
</div>
</template>
<script>
export default {
name: "App",
data: () => ({
items: [1, 1]
}),
methods: {
addItem() {
this.items.push(1);
},
removeItem() {
this.items.pop();
}
}
};
</script>
<style>
#app {
text-align: center;
color: white;
margin-top: 60px;
background: blue;
height: auto;
transition: all 1.5s ease;
}
.box {
padding: 15px;
}
</style>
You need a measurement unit for it to be animated. height: auto won't do it.
You will need to compute the items height in JS.

Vue Native Router gives error not being used

So I am creating an app for a school project and I am trying to make a navigation screen.
I have a screen with 2 buttons and I am trying to make them work. If I click/press on the button I want to go to a diffrent screen.
I am new to this, this is the first time I am using Vue Native.
Current code:
<template>
<div id="app">
<HelloWorld msg="CarnavalXL"/>
<div id="nav">
<button #press="goToParadeScreen" class="nav-button">Optochten</button>
<button href="screens/Parades.vue" class="nav-button" title="Niews">Nieuws</button>
<router-link to="Parades" class="nav-button">Parades</router-link>
</div>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'CarnavalXL',
components: {
HelloWorld,
AppNavigator
},
props: {
navigation: {
type: Object
}
},
methods: {
goToPAradeScreen() {
this.navigation.navigate("Parades");
}
}
}
import {
createAppContainer,
createStackNavigator,
} from "vue-native-router";
import Parades from "./Parades.vue";
this.navigation.navigate("Parades", {/* options go here */});
const StackNavigator = createStackNavigator(
{
Parades: Parades,
},
{
initialRouteName: 'Parades',
}
);
const AppNavigator = createAppContainer(StackNavigator);
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
margin-left: 25vw;
margin-right: 25vw;
}
.nav-button {
background-color: rgba(0, 0, 0, 0.3);
padding: 100px 0px;
width: 20vw;
display: inline-block;
margin: 5px;
color: #fff;
font-size: 40px;
font-weight: 800;
}
</style>
I get the following error:
Failed to compile.
./src/App.vue
Module Error (from ./node_modules/eslint-loader/index.js):
D:\carnavalxl\src\App.vue
19:5 error The "AppNavigator" component has been registered but not used vue/no-unused-components
✖ 1 problem (1 error, 0 warnings)
I followed the guide on the site of Vue Native
I do not know what is going wrong here
It's because your only importing the HelloWord component and not importing AppNavigator component. If you have a component called AppNavigator you have to import it like the HelleWorld like this:
import HelloWorld from './components/HelloWorld.vue'

Polymer : Property 'response' bound to attribute 'last-response' not found in 'properties' for element 'menu-kaart'

I'm working on a project in polymer and while I was busy, I get this error:
Property 'response' bound to attribute 'last-response' not found in 'properties' for element 'menu-kaart'
Since I am new to polymer, I don't know what to do. I searched over the internet and I can't find the solution.
Here is the code:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/iron-ajax/iron-ajax.html">
<dom-module id="menu-kaart">
<template>
<style>
:host {
display: block;
background-color: maroon;
padding: 15px;
color: deepskyblue;
}
body {
margin: 0px;
}
h1 {
color: antiquewhite;
text-decoration: none;
}
h3, p {
color: antiquewhite;
}
div {
color: white;
}
</style>
<iron-ajax
auto
url="/cgi-bin/menulezen.py"
handle-as="json"
last-response="{{response}}">
</iron-ajax>
<h1>Menukaart</h1>
<template is="dom-repeat" items="{{response}}">
<div>
<h3>{{item.Gerecht}}</h3>
<p>Ingredienten: {{item.Ingredienten}} <br>
Opmerkingen: {{item.Opmerkingen}}</p>
</div>
</template>
</dom-module>
<script>
Polymer({
is: 'menu-kaart',
properties: {
}
</script>
Try modifying your script tag to
<script>
Polymer({
is: 'menu-kaart',
properties: {
response: {
type: Object
}
}
</script>
I'd also recommend you to upgrade your Polymer version to latest 1.x i.e. 1.8 or something relatively newer as Polymer has done a lot of fixes/changes since 1.3.
Lastly, i'll recommend you to read some documentations or some video tutorials to have a better understanding of Polymer

WinJS.BackButton sizes

I have this html tag which reffers to the backButton provided by the WinJS library:
<button data-win-control="WinJS.UI.BackButton"></button>
I want to change its size. How can I do that? I tried using CSS by adding the ID "backButton" and font-size OR width/height properties, like this:
#backButton {
font-size: small;
}
#backButton {
height: 30px;
width: 30px;
}
EDIT: Code added and a picture of what happens when changing the values of width/height of the button.
// For an introduction to the Page Control template, see the following documentation:
// http://go.microsoft.com/fwlink/?LinkId=232511
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/anime/anime.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
// TODO: Initialize the page here.
this.renderAnimeInfo(Identifier.file);
},
unload: function () {
// TODO: Respond to navigations away from this page.
},
updateLayout: function (element) {
/// <param name="element" domElement="true" />
// TODO: Respond to changes in layout.
},
renderAnimeInfo: function (id) {
// Path for the anime data.
var path = "data/animes.json";
// Retrieve the .json.
WinJS.xhr({ url: path }).then(
function (response) {
var json = JSON.parse(response.responseText);
for (var i = 0; i < json.length; i++) {
if (json[i].file == id) {
var animeData = json[i];
break;
}
}
},
function (error) {},
function (progress) {}
);
},
});
})();
.right {
float: right;
}
.left {
float: left;
}
.active {
background-color: blue;
}
#animeDetails {
background: red;
height: 100%;
width: 300px;
float: left;
}
#animeInfo {
display: -ms-grid;
height: 100%;
width: calc(100% - 300px);
float: right;
}
#navbar {
-ms-grid-row: 1;
padding: 20px 25px;
}
#navbar .right button {
margin-right: 4px;
}
#navbar input {
width: 150px;
}
#details {
-ms-grid-row: 2;
padding: 0 25px;
text-align: justify;
white-space: pre-line;
}
#details h3 {
width: 100%;
padding: 5px 0;
border-bottom: 1px solid #bebebe;
margin-bottom: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>anime</title>
<link href="anime.css" rel="stylesheet" />
<script src="anime.js"></script>
</head>
<body>
<div id="animeDetails"></div>
<div id="animeInfo">
<div id="navbar">
<div class="left">
<button class="left" data-win-control="WinJS.UI.BackButton"></button>
<h3>Back</h3>
</div>
<div class="right">
<button type="button" class="active">Details</button>
<button type="button">Episodes</button>
<button type="button">Characters</button>
<button type="button">Staff</button>
<input type="search" placeholder="Search" />
</div>
</div>
<div id="details">
<div id="synopsis">
<h3>Synopsis</h3>
<span>
</span>
</div>
</div>
</div>
</body>
When using the width/height properties, what happens is that the button does resize to the specified value, but the icon inside (which is not a background) doesn't. http://i.imgur.com/lMqmL0G.png
Possibly you have to set display: inline-block to button because the width of an element with display: inline (the default for buttons) is exactly the same as its content because it only takes up the space needed to display its contents so try with:
With id selector
#backButton {
height: 30px;
width: 30px;
display: inline-block;
}
<button id="backButton" data-win-control="WinJS.UI.BackButton"></button>
With style inline
<button data-win-control="WinJS.UI.BackButton" style="width: 30px; height: 30px; display: inline-block"></button>
Try to set the styles to child element .win-back
#backButton .win-back{
/*---styles---*/
}
You haven't given your button an ID. The CSS does not know what tag to link to.
<button id="backButton" data-win-control="WinJS.UI.BackButton"></button>
edit: you may find the following reference useful CSS Selectors