conditional rendering to display component in vue - javascript

I have a parent comp which content should be displayd conditionally
when the userinput variable is false
The <div class="parent">
should be removed and the PopUp component displayed
I tried to use `v-if` but dont know how to remove the entire div with it elements
I could only change single elements with v-if else
parent comp
<template>
<div>
<h1>header</h1>
<div class="parent">
<h2>infos</h2>
<button>x</button>
</div>
</div>
</template>
<script>
import PopUp from './PopUp.vue';
export default {
data() {
return {
userinput: true,
}
}
}
</script>
child component - PopUp
<template>
<div>
<button>x</button>
<p>errorMessage</p>
</div>
</template>

Add v-if="userinput" doesn't work ?
If I understand what you want, you should have something like this :
// parent comp
<template>
<div>
<h1>header</h1>
<div v-if="userinput" class="parent">
<h2>infos</h2>
<button>x</button>
</div>
<PopUp v-else/>
</div>
</template>
Do not hesitate to read the Vue.js documentation

Related

Transition on conditional rendering in react JS

I have this conditional render function ready and it works fine.
render() {
if (this.state.guess === 'guessing') {
return (
<div style={rightBarStyle.guessingGameStyle}>
<div style={rightBarStyle.guessingGameStyle.quizBlockStyle}>
<h3> Who is this? </h3>
<ul className={'optionsContainer'}>
<PeopleNames onClick={(e) => this.handleClick(e)}/>
</ul>
</div>
<div style={rightBarStyle.guessingGameStyle.imgBlockStyle}>
<img style={rightBarStyle.guessingGameStyle.imgBlockStyle.image} src={imageLink}
alt={"profile pic"}/>
</div>
</div>
)
}
else if (this.state.guess === 'correct') {
return (
<div style={rightBarStyle.guessingGameStyle}>
<div style={rightBarStyle.guessingGameStyle.quizBlockStyle}>
<FadeIn>
<p className={['details','title'].join(' ')}>{name} </p>
<p className={['details','designation'].join(' ')}>Software Developer</p>
<p className={['details','team'].join(' ')}>Software Department</p>
</FadeIn>
</div>
<div style={rightBarStyle.guessingGameStyle.imgBlockStyle}>
<img style={rightBarStyle.guessingGameStyle.imgBlockStyle.image} src={imageLink}
alt={"profile pic"}/>
</div>
</div>
)
}
else return <div></div>
}
Issues:
I need to apply a transition whenever new DOM elements are rendered on state change. I read about CSSTransitions but they work on child elements.
Here is the sandbox link on which I want to have a smooth transition onclick of the button: SandBox
I have to include that last 'else' otherwise it throws an error that render didn't find anything to be rendered on DOM. It works but is there a workaround for this? It does not look neat.

Injecting html - using slot or v-html?

So here’s my case:
I’m creating a modal via:
<Modal id="modal">
<my-component></my-component>
</Modal>
Now I want the content inside the modal to be dynamic, so I can put <input> or <table> or w/e. I’ve tried using slots (it works), but it isn’t really dynamic. I’m wondering if I missed something that would allow the slot to be a bit more dynamic.
Here’s how my modal is set up:
<div
:id="id"
class="main"
ref="main"
#click="close_modal"
>
<div ref="content" class="content" :style="{minHeight: height, minWidth: width}">
<div ref="title" class="title" v-if="title">
{{ title }}
<hr/>
</div>
<div ref="body" class="body">
<slot></slot>
</div>
</div>
</div>
I think using slots is a good choice for this. With the introduction of slot-scope in 2.5, you basically get a reverse property capability where you can set defaults within the child component and access them within the parent. They are of course completely optional to use and you're free to place whatever content you like in the slots.
Here's an example component that would allow you to customize the header, body and footers as you see fit:
// MyModal.vue
<template>
<my-modal>
<slot name="header" :text="headerText"></slot>
<slot name="body" :text="bodyText"></slot>
<slot name="footer" :text="footerText"></slot>
</my-modal>
</template>
<script>
export default {
data() {
return {
headerText: "This is the header",
bodyText: "This is the body.",
footerText: "This is the Footer."
}
}
}
</script>
// SomeComponent.vue
<template>
<div>
<my-modal>
<h1 slot="header" slot-scope="headerSlotScope">
<p>{{ headerSlotScope.text }}</p>
</h1>
<div slot="body" slot-scope="bodySlotScope">
<p>{{ bodySlotScope.text }}</p>
<!-- Add a form -->
<form>
...
</form>
<!-- or a table -->
<table>
...
</table>
<!-- or an image -->
<img src="..." />
</div>
<div slot="footer" slot-scope="footerSlotScope">
<p>{{ footerSlotScope.text }}</p>
<button>Cancel</button>
<button>OK</button>
</div>
</my-modal>
</div>
</template>
<script>
import MyModal from './MyModal.vue';
export default {
components: {
MyModal
}
}
</script>

How can I get the HTML from a slot with Vue?

How can I get the HTML from a slot with Vue?
<template>
<div>
<slot></slot>
<pre>{{ code }}</pre>
</div>
</template>
I want to get the html from <slot></slot> and show it in the <pre></pre>
Currently I have tried to do this
mounted: function () {
this.code = document.getElementById("demo-" + this.title).innerHTML;
}
but that gets the code after webpack and that is not what I want. I just want the code that gets put in.
<Demo>
<h1>This is a header</h1>
</Demo>
Should turn into
<div>
<h1>This is a header</h1>
<pre><h1>This is a header</h1></pre>
</div>

VueJS - Pass slot to child of child component

I have a list and a list_item component that I reuse a lot inside my application. On a simplified form:
contact_list.vue
<template lang="pug">
.table
.table-header.table-row
.table-col Contact
.table-col Info
.table-body
contact-list-item(v-for='contact in contacts',
:contact='contact',
#click='doSomething()')
</template>
contact_list_item.vue
<template lang="pug">
.table-row(#click='emitClickEvent')
.table-col {{ contact.name }}
.table-col {{ contact.info }}
</template>
When I use contact_list inside a specific component, I want to be able to send a slot that will add some new columns to the contact_list_item component. This slot will use data of the specific contact that is being rendered inside that contact_list_item component to generate the new columns.
How could I achieve that? Is using slot the best approach?
Thanks in advance.
Slots are the best approach and you will need to use a scoped slot for the contact-list-item component. I'm not really familiar with pug, so I will use HTML for the example.
In contact-list you would add a slot. Notice in this case that the contact is being passed as a property. This is so we can take advantage of scoped slots.
<div class="table">
<div class="table-header table-row">
<div class="table-col">Contact</div>
<div class="table-col">Info</div>
</div>
<div class="table-body">
<contact-list-item v-for='contact in contacts'
:contact="contact"
#click="doSomething"
:key="contact.id">
<slot :contact="contact"></slot>
</contact-list-item>
</div>
</div>
Then add a slot to the contact-list-item.
<div class="table-row" #click="emitClickEvent">
<div class="table-col">{{contact.name}}</div>
<div class="table-col">{{contact.info}}</div>
<slot></slot>
</div>
Finally, in your Vue template, use the scoped template.
<div id="app">
<contact-list :contacts="contacts">
<template scope="{contact}">
<div class="table-col">{{contact.id}}</div>
</template>
</contact-list>
</div>
Here is a working example. I have no idea what your styles are but notice the id column is now displayed in the contact-list-item.
You can use template for registering slot to the child of child component.
There is also a case when you want to have many named slots.
child.vue
<template>
<div>
<h2>I'm a father now</h2>
<grandchild :babies="babies">
<template v-for="(baby, id) in babies" :slot="baby.name">
<slot :name="baby.name"/>
</template>
</grandchild>
</div>
</template>
grandchild.vue
<template>
<div>
<p v-for="(baby, id) in babies" :key="id">
<span v-if="baby.isCry">Owe...owe...</span>
<slot :name="baby.name">
</p>
</div>
</template>
parent.vue
<template>
<div>
<h2>Come to grandpa</h2>
<child :babies="myGrandChilds">
<button slot="myGrandChilds[2].name">baby cry</button>
</child>
</div>
</template>
Add to #DrSensor's answer.
In Vue3, you should use dynamic slot name.
<template>
<div>
<h2>I'm a father now</h2>
<grandchild :babies="babies">
<template v-for="(baby, id) in babies" #[baby.name]>
<slot :name="baby.name"/>
</template>
</grandchild>
</div>
</template>
To translate several slots one level down conveniently to use the method described at this link, and if you modify it a little, perhaps you will be able to transfer it deeper.

Online Example (CSS of a Cube) inside React

I am trying to reproduce this cube inside of a webpage I am making using react (i am very new to react, so this question might be stupid)
https://codepen.io/jordizle/pen/haIdo/
So, I created a component, which contains the HTML structure for the cube.
class Cube extends Component {
render() {
return (
<div className="cube">
<div id="wrapper">
<div class="viewport">
<div class="cube">
<div class="side">
<div class="cube-image">1</div>
</div>
<div class="side">
<div class="cube-image">2</div>
</div>
<div class="side">
<div class="cube-image">3</div>
</div>
<div class="side">
<div class="cube-image">4</div>
</div>
<div class="side">
<div class="cube-image">5</div>
</div>
<div class="side">
<div class="cube-image active">6</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
Then, I simply added the CSS from the above website to a separate file, which I imported, like so:
import './ProductPage.css';
(see link above for css. The CSS is just copy pasted).
Finally, I created another component, which should render the cube, when it itself is rendered:
class NewProductPage extends Component {
constructor(props) {
super(props);
this.state = {
img: null,
};
this.onDrop = this.onDrop.bind(this);
}
onDrop(acceptedFiles){
this.setState({
img: acceptedFiles[0].preview,
})
}
render(){
return (
<div>
<Cube />
<div className="DropPicBox">
<DropZone onDrop={this.onDrop}>
{this.state.img ?
<div>
<img className="PicBox" src={this.state.img} />
</div>
: null}
</DropZone>
</div>
</div>
);
}
}
This is rendered, but incorrectly:
My question is: is there something about the way react applies CSS that would change the way the cube looks? I used jfiddle to model this same cube using HTML and CSS from this website: https://codepen.io/jordizle/pen/haIdo/
And the cube looked correctly:
https://jsfiddle.net/jfj3muug/#&togetherjs=q2dv8HIMza
In JSX, to specify the class of an element, you have to use className, not class. E.g.:
<div className="foo">...</div>
instead of
<div class="foo">...</div>
You're doing that in some places, but Cube (your first codeblock) has class in several places.

Categories