Vue dynamically add Component - html

For my Vue project i have a login component and a responsive overlay component.
I built it that way so i could load my responsive overlay component with the needed content using props.
To help you understand the structure, it looks like the following:
Home.vue
<script setup lang="ts">
import ResponsiveOverlay from '../components/responsiveOverlay.vue'
</script>
<template>
<div class="overlayWrapper">
<ResponsiveOverlay v-if='showDisplay' :switchContent='switchOverlayContent'></ResponsiveOverlay>
</div>
</template>
ResponsiveOverlay.vue
<script setup lang="ts">
import LoginOverlay from '../components/loginOverlay.vue'
const props = defineProps({
switchContent: String,
})
</script>
<template>
<div class="responsiveOverlayWrapper">
<LoginOverlay v-if='switchContent == "login"'></LoginOverlay>
</div>
</template>
LoginOverlay.vue
<template>
<h1>Login</h1>
</template>
SwitchOverlayContent is a string variable, that (as of now) is hardcoded to contain "login"
As you can see, i tried using v-if="showDisplay" with the ResponsiveOverlay in a hope i could just toggle the bound bool and it would show, which did not work, probably because the v-if is only ran when loading the page.
So what i would need is a solution where i could click a button which would then set switchOverlayContent dynamically to "login" and then display the ResponsiveOverlayContent.
How would i achieve said behaviour and also, is my strategy of having a component inside of a component viable?

Related

Vue: Pass function into parent component

Okay, I'm new to Vue and trying to simplify my problem as much as I can do.
I have two components: NewsItem, NewsItemList
NewsItem:
<template>
<div>
<h1>A title</h1>
<a #click="aFunctionDeclaredInThisComponent">Link</a>
</div>
</template>
NewsItemList:
<template>
<NewsItem />
<div>A mystic box</div>
</template>
I want to show/hide the mystic box in NewsItemList, if the function aFunctionDeclaredInThisComponent is activated, which is in NewsItem. I would like to toggle show/hide with a active state in CSS.
My problem is, I don't know how to pass the function into the parent component. Please note, that I use <script setup>.
Thank you!
Not sure what you are trying to do, but I wrote you a minimal example of how to send data from child component to parent component. Check it out here.
The idea is to emit an event from the child and listen to it in the parent. Don't mind the naming I used, just try to understand how I'm interacting with the data in parent component via child one and try to implement it into your code:
Parent:
<template>
<Comp #my-var="callback" />
<p
v-text="`Clicked hide from child? ${test}`"
/>
<div v-show="! test">
I'm the parent div
</div>
</template>
<script setup>
import { ref } from 'vue'
import Comp from './Comp.vue'
const test = ref(false)
const callback = data => test.value = data
</script>
Child:
<template>
<button
v-text="'click to hide parent div'"
#click="doEmit()"
/>
</template>
<script setup>
const emits = defineEmits(['myVar'])
const doEmit = () => emits('myVar', true)
</script>

Unable to add custom content between Reusable Components with Vue.js

I am trying to create a reusable button using components but the new content Sign In applied to the custom tag to replace the default content Custom Text is not working.
Vue 2.6.11 | #vue/cli 4.5.13
I also checked this tutorial
<!-- ButtonWave.vue component -->
<template>
<button type="button" class="btn custom-btn">
Custom Text
</button>
</template>
Importing the custom button
<!-- MainMenu.vue component -->
<template>
<button-wave>Sign In</button-wave>
</template>
<script>
import ButtonWave from './ButtonWave.vue'
export default {
name: 'main-menu',
components: {
ButtonWave
},
...
</script>
The reproductable code is available at https://github.com/axelmukwena/risksis
You missed the part where the writer of the article mentioned the need of a slot:
Doing this should add a button element to the page with text that says “Button”. The text content is coming from the fallback content defined within the Button component. Fallback content is defined by putting content between the tags for a component. More can be read about slots and fallback content here.
Your template should look like this:
<template>
<button
v-wave="{
color: '#0054aa',
easing: 'ease-out',
initialOpacity: 0.5,
finalOpacity: 0.1,
cancellationPeriod: 75
}"
type="button"
class="btn custom-btn"
>
<slot>Custom Text</slot>
</button>
</template>
I would advise you to check out props and named slots before going further.
Good luck with your project!

How to make data accessible to a React Component when data exists outside of states scope

. .
I am currently using React VR for a school project, but incorporating vanilla javascript into the index.html to create a static HTML UI. In this case I am using an HTML5 form to post data to my back end, yet still, I would like to optimistically render the data using a React component rather than have to retrieve the data from the server.
My data is created in the HTML element, and it needs to make its way into a React Component.
I don't think refs will work, as the research I have done shows that they are for accessing data which is being generated by a React component, and in my case, I am looking for the data to flow from the HTML to the React Component.
~ JAVASCRIPT & HTML ~
//Accepts the Input
<form id='idea-form'>
<input type="text" id="hiddenInput" maxlength=95 autocomplete=off>
</form>
// Initialize the React VR application.
ReactVR.init(
'../index.vr.bundle?platform=vr&dev=true',
document.body
);
I've included my component here, minus imports and exports.
The component maps an array of strings, converts them to JSX, then renders components with the array elements as the text props for the component.
In my case,
//========== IdeaContainer Component ==========
class IdeaContainer extends Component {
//---------- Other Methods ----------
mapIdeasContentToJSX(ideasObjArr) {
newIdeas = [...ideasObjArr]enter code here
ideasJSX = newIdeas.map((idea) => {return (<IdeaText
text={idea.content}
y={Math.random() * 30}
z={Math.random() * -80}
/>)})
return ideasJSX
}
//---------- Lifecycle Methods ----------
componentDidMount(){
this.props.preLoadIdeas()
}
render(){
return(
<View>
{this.mapIdeasContentToJSX(this.props.ideaList)}
</View>
)
}
}
This is the code which lives in the index.html, which exists outside the scope of my React components, meaning I cannot pass it as props or set it to state, as far as I know.
The element with id of 'container' is where the data is being entered, which then needs to make its way to the React Component
<div>
<div id='logoDIV'class="relative" >
<img id='logoIMG' src='./logo.png' draggable="false">
</div>
</div>
<div id="container" style='position: fixed; z-index: 2; bottom: 1%; right: 22%;'>
<div id="input"></div>
<form id='idea-form'>
<input type="text" id="hiddenInput" maxlength=95 autocomplete=off>
</form>
</div>
<canvas id="cloudCover"></canvas>
<!-- When you're ready to deploy your app, update this line to point to your compiled client.bundle.js -->
<script src="./client.bundle?platform=vr"></script>
<script src="./input.js"></script>
<script src='./clouds.js'></script>
<script>
ReactVR.init(
// When you're ready to deploy your app, update this line to point to
// your compiled index.bundle.js
'../index.vr.bundle?platform=vr&dev=true',
document.body
);
</script>
<script>
let x = document.body.querySelector('body > div:nth-child(8) > div > a:nth-child(2)')
x.style.bottom = '100px'
</script>
You are looking for refs.
<input
type="text"
id="hiddenInput"
maxlength=95
autocomplete=off
ref={(input) => { this.textInput = input; }} />
Then you can access the input value like this:
this.textInput.value
https://reactjs.org/docs/refs-and-the-dom.html

Recommendations for managing multiple instances of the same polymer element in a page?

I have a general question. One of the major benefits of building a new polymer element is that it can be used like a native HTML element in a page. So, depending on the element that you build, it's logical that you would be able to add multiple instances of that element in a page.
Say I build a simple task list polymer element that has multiple views. A simple view that just lists the task names in a list and a detailed view that list the tasks and many other properties of the task in a list.
Then I add the element to my page multiple times. Maybe I want one instance of the element to list tasks related to Home and another to list tasks related to Work. But I want to send a link to someone with the Home task list opened in the simple view and the Work task list opened in detailed view. Or maybe I want the Home task list opened in edit mode and the Work task list opened in view mode.
How would you build the element so that you can change attributes/settings to more then one of these elements on a page?
The beauty of polymer is that you can change your component view by just adding / changing attributes to it.
Create custom tags and provide specific attributes depending on your requirement (HOME / WORK profile), and change your view accordingly.
Example:
Step 1: Create task container
<polymer-element name="task-list" noscript>
<template>
<h3>Tasklist</h3>
<core-menu id="tasks">
<content></content>
</core-menu>
</template>
</polymer-element>
Step2: Create task component
<polymer-element name="add-task" attributes="label detail">
<template>
<div id="task">
<input type="checkbox" id="tick" on-click="{{lineThrough}}" /> {{label}}
<div style="color:#999;margin: 5px 25px;">
{{detail}}
</div>
</div>
</template>
<script>
Polymer('add-task', {
lineThrough: function() {
this.$.task.style.textDecoration = this.$.tick.checked ? 'line-through': 'initial';
}
});
</script>
</polymer-element>
And now using above components, you can create your basic task list:
<task-list>
<add-task label="Learn Polymer" detail="http://www.polymer-project.org/"></add-task>
<add-task label="Build something great" detail="create polymer element"></add-task>
</task-list>
Screenshot
Now, To have control over changing task view (list / detailed / editable). Just add 2 attributes to task-list component. To control child view add-task from parent task-list element, you need to publish properties of your child element.
Your child component should be:
<polymer-element name="add-task" attributes="label detail">
<template>
<div id="task">
<template if="{{isEditable}}">
<input value="{{label}}" />
</template>
<template if="{{!isEditable}}">
<input type="checkbox" id="tick" on-click="{{lineThrough}}" /> {{label}}
</template>
<template if="{{isDetailed}}">
<div style="color:#999;margin: 5px 25px;">
{{detail}}
</div>
</template>
</div>
</template>
<script>
Polymer('add-task', {
publish: {
isDetailed: false,
isEditable: false
},
lineThrough: function() {
this.$.task.style.textDecoration = this.$.tick.checked ? 'line-through': 'initial';
}
});
</script>
</polymer-element>
Parent component with required attributes
<polymer-element name="task-list" attributes="editable detailed">
<template>
<h3>Tasklist</h3>
<core-menu flex id="tasks">
<content></content>
</core-menu>
</template>
<script>
Polymer('task-list', {
editable: false,
detailed: false,
domReady: function() {
var items = this.$.tasks.items;
for(var i = 0; i < items.length; i++) {
items[i].isDetailed = this.detailed;
items[i].isEditable = this.editable;
}
}
});
</script>
</polymer-element>
That's it, now you can control your task view by specifying required attributes to your parent component.
<task-list detailed editable>
<add-task label="Learn Polymer" detail="http://www.polymer-project.org/"></add-task>
<add-task label="Build something great" detail="create polymer element"></add-task>
</task-list>
Screenshots
With detailed and editable attributes
Without detailed and editable attributes

Dart passing data to a dynamically created polymer element [duplicate]

This question already has an answer here:
When dynamically adding dart polymer elements, how do I get observable variables to on DOM
(1 answer)
Closed 8 years ago.
I have read this thread about how to pass data to a polymer element
Button click in polymer dart does not work; needs polymer-element
But however, if I want to pass data to a programmatically created element by using createElement() in polymer.dart, there's no wrapping template. How am I going to pass the data as mentioned above?
Btw, even though I think dart is a really cool language (I dislike JavaScript,) I found polymer in dart maybe still not ready yet. A lot of things are not documented and have to go though examples or ask here.
Thanks,
Yi
I think you should remove the start()-function from MyElementElement-class and add it to upper level. Basically you shouldn't have any reference in custom-element to upper level objects. Now the custom element is not reuseable, it works only within this context.
I have searched for a long time but anything work. Only one solution work fine for me: https://stackoverflow.com/a/20067111/189411
Here is my example on how i passed data to a dynamically created custom polymer-element.
My intention was, click on an "a href" and load a polymer-element in a container div.
polymer_element.html
<polymer-element name="my-element">
<template bind>
<p> {{ mytext }} </p>
</template>
<script type="application/dart" src="polymer_myelement.dart"></script>
</polymer-element>
polymor_element.dart
import 'dart:html';
import 'package:polymer/polymer.dart';
import 'package:custom_element/custom_element.dart';
#CustomTag('polymer-myelement')
class MyElementElement extends PolymerElement with ObservableMixin {
bool get applyAuthorStyles => true;
#observable String mytext = "initial text";
void start() {
query('#a href to click').onClick.listen((MouseEvent event){
query('.container').children.clear();
var myElem = createElement('polymer-myelement');
MyElementElement myel = myElem.xtag;
myel.mytext = "i changed the text now or import w/e you want";
query('.container').children.add(myElem);
});
}
}
main() {
MyElementElement el = new MyElementElement();
el.start();
}
index.html
<head>
<link rel="import" href="polymer_myelement.html">
and everything you need ...
</head>
<body>
<a href to click>click me for new text</a>
<div class="container">
<!-- START OF MAINCONTAINER -->
<!-- END OF MAINCONTAINER -->
</div>
</body>
So here is the explanation:
In my main() i just run my start() function and set an onclickListener for my navigation bar href. When i click my href now, i just clear all children in my "div class="container", because i always want a clear div before i insert my polymer-elements.
Now create a polymer-Element with "createElement('polymer-mylement');".
Create a MyElement object and assign the polymer-element "xtag" to it.
Now you have access to all the properties and can change them.
Just add your created Element to your div and you are done.
You just dynamically created a polymer-element, assigned your new data to it and see it in your index.html