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!
Related
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?
in angular 2 I need to create a large html-template with redundant parts.
Therefore I want to create multiple html-templates and put them together by including them in the main html-file (like ng-include in angular1)
But how can I include sub-templates in the main-template?
example:
<!-- test.html -->
<div>
this is my Sub-Item
<!-- include sub1.html here-->
</div>
<div>
this is second Sub-Item
<!-- include sub2.html here-->
</div>
-
<!-- sub1.html -->
<div>
<button>I'am sub1</button>
</div>
-
<!-- sub2.html -->
<div>
<div>I'am sub2</div>
</div>
You can create components like sub1 sub2 etc. And On those child components add these html files as template .
On main html call the component selectors respectively. It will work
Let me tell you first of all that ng-include from Angular1.x is not supported by Angular2 so obviously $Compile is not present in Angular2. So, you can go ahead with CRF-ComponentFactoryResolver as shown here to add HTML dynamically with angular context.
DEMO--(CFR) : https://plnkr.co/edit/YdRlULhWQR3L3akAr2eb?p=preview
If your HTML piece has angular context, you should use CFR-ComponentFactoryResolver.
As in sub1.html, you have button, you might want to click it and fire its click event. This can be achieved with CFR as shown below,
You can do lot with CRF. This is probably the easiest example.
#Component({
selector: 'my-app',
template: `
<button (click)="addComponents()">Add HTML (dynamically using CRF)</button>
<h1>Angular2 AppComponent</h1>
<hr>
<div>
<h5>sub1.html goes here</h5>
<div class="container">
<template #subContainer1></template>
</div>
</div>
<hr>
<h5>sub2.html goes here</h5>
<div class="container">
<template #subContainer2></template>
</div>
`,
})
export class App {
name:string;
#ViewChild('subContainer1', {read: ViewContainerRef}) subContainer1: ViewContainerRef;
#ViewChild('subContainer2', {read: ViewContainerRef}) subContainer2: ViewContainerRef;
constructor(
private compFactoryResolver: ComponentFactoryResolver
) {
this.name = 'Angular2'
}
addComponents() {
let compFactory: ComponentFactory;
compFactory = this.compFactoryResolver.resolveComponentFactory(Part1Component);
this.subContainer1.createComponent(compFactory);
compFactory = this.compFactoryResolver.resolveComponentFactory(Part2Component);
this.subContainer2.createComponent(compFactory);
}
}
}
I have defined a custom DOM element, but when placed inside a form, it does not submit it. How can I get the form to submit when I click the button?
<form action="/foo" method="GET">
<my-button type="submit">click me</my-button>
</form>
This is the prototype configuration for the custom element:
myButton = Object.create(HTMLButtonElement.prototype);
The template for the button looks like this:
<template>
<button type="submit" id="button"><content></content></button>
</template>
Came across this question today, but found a more modern alternative subsequently: web components can now be native form elements. There's a great read on the topic here.
The long and the short of it is you can now associate custom components with a form, meaning they're included in the form's elements property - a HTMLFormControlsCollection of all the elements controlled by the form.
To do this, you need to add the following to your component:
class MyComponent extends HTMLElement {
static get formAssociated() { return true; }
constructor() {
super();
this.internals = this.attachInternals();
}
}
this.internals will then contain everything you need to interact with the form in question, e.g. this.internals.form, this.internals.setFormValue(), this.internals.checkValidity().
For the submit button, you could, for example, use:
connectedCallback() {
const { internals: { form } } = this;
this.buttonEl.addEventListener('click', () => form.submit());
}
You are doing it wrong. Though event bubbling from shadow DOM to owner document is somehow possible, it’s tricky and in general is a wrong approach. Instead of hiding button into shadow, one should use is= attribute of button:
<form action="/foo" method="GET">
<!--my-button type="submit">click me</my-button-->
<!-- ⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓⇓ -->
<button type="submit" is="my-button">click me</button>
</form>
More info.
When your custom element extends a native element like HTMLButtonElement, you can no longer use a custom tag name like <my-button> (unfortunately). You have to use the native tag with the is= attribute:
<button type="submit" is="my-button">
If you do not extend a native element (called "type extension" in the spec), then you can use your custom tag name. Type extension example in the spec
I using this template.
<template repeat = "{{cover in covers | keys}}">
<div class ='item'>
<img src="{{cover}}"></img>
</div>
</template>
and in my polymer script
domReady: function () {
//aplly some css
}
but when i debug the repeat is not over when the ready event is fired, so my css style changes is not happening.
It would be best to know what CSS you're trying add. Typically, you should not try to manage the DOM of a <template repeat> yourself. Instead, tweak it with your data model. For example, you could dynamically apply the "show" class to the image based on a property it sets:
<template repeat = "{{cover in covers | keys}}">
<div class ='item'>
<img src="{{cover}}" class="{{ {show: cover.show} | tokenList }}">
</div>
</template>
or do something similar by setting an inline style.
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