Is it possible to load custom elements dynamically?
Let's say my viewModel looks like this:
export class MyViewModel {
attached() {
$(".content").prepend("<card></card>");
$(".content").prepend("<otherCard></otherCard>");
}
}
Why is aurelia not rendering my "cards". Is there any way i can achive similar behaviour?
Adding those cards directly in HTML works great, but i need a more modular approach.
Thanks
Check out the <compose view-model="card" /> element in the docs. It should give you what you're looking for.
Related
I have a custom LitElement and inside it, I need to have a button that will dynamically append new custom elements (preferably using TemplateResult objects generated by html function) inside a container:
import { LitElement, html, render } from "lit";
import { customElement } from "lit/decorators.js";
#customElement('example-custom-component')
class CustomComponent extends LitElement {
render() {
return html`
<div id="custom-el-container">
</div>
<button #click=${this.appendNewCustomEl}>click me!</button>
`;
}
appendNewCustomEl() {
const templateToAppend = html`
<another-custom-component>
some other things added here
</another-custom-component>
`;
render(templateToAppend, this.shadowRoot?.querySelector('#custom-el-container'));
}
}
As you can see above I tried to achieve it by using the render function, but instead of appending it at the end of the container, I'm simply overwriting the content of the div. What am I doing wrong? What's the best approach to achieve those results? Please help.
EDIT:
New example for my question from comments about click events:
appendNewCustomEl() {
this.shadowRoot!.querySelector('#custom-el-container').insertAdjacentHTML("beforeend", `
<another-custom-component>
<button #click=${this.functionFromCustomComponent}>click me!</button>
</another-custom-component>
`)
}
If you really want to do it with lit-html and your container's content is purely what you are dynamically rendering on each button click, (i.e. not server side rendered content) or you are using lit-html v2 then you could have a list and track what you have rendered. something like:
items=[];
appendNewCustomEl() {
this.items.push(null);
const templatesToAppend = this.items.map(() => html`
<another-custom-component>
some other things added here
</another-custom-component>
`);
render(templatesToAppend, this.shadowRoot?.querySelector('#custom-el-container'));
}
in general what lit-html is good at and tries to achieve is an optimal re-render of markup when only parts are changed. not necessary a template engine alternative to handlebars, mustache and co.
In your example, you don't need it and could do it simply without lit-html:
appendNewCustomEl() {
this.shadowRoot!.querySelector('#custom-el-container').insertAdjacentHTML("beforeend", `
<another-custom-component>
some other things added here
</another-custom-component>
`)
}
I've slightly modified your example code to be more idiomatic Lit. Instead of using a querySelector and insertAdjacentHTML, it is preferred to render the array of templates declaratively. This has the added benefit that your functionFromCustomComponent event bindings "just work".
I've written the full example in a Lit playground.
The list of templates are stored in a reactive property, this.templates that schedules an efficient update whenever the list is updated.
Then the this.appendNewCustomEl method can push new templates to the list, and an automatic efficient render happens automatically.
this.templates is rendered into the #custom-el-container div using an expression:
<div id="custom-el-container">
${this.templates}
</div>
See Lit expressions documentation for other examples.
In my linked example, the list of templates turn blue when clicked to demonstrate the event working.
Not necessary but related, Lit.dev has a tutorial all about Working with lists that goes much more in depth if you're curious.
I'm building a Svelte component library to be consumed using JavaScript only. At a later stage also by other Svelte applications as an additional option.
I want to avoid Svelte's custom element feature, since there are limitations with true Web Components and its Shadow DOM.
Currently the component is instantiated like this:
<div id="my-component"></div>
<script>
document.addEventListener("DOMContentLoaded", function (event) {
new MySvelteComponent({
target: document.getElementById("my-component"),
props: {
firstProp: true,
secondProp: "some value"
}
});
});
</script>
Now I would like to provide a more elegant way by defining a HTLM5 custom tag like:
<my-component firstProp="true" secondProp="some value">
What is a good way to implement this?
found it: github/svelte-tag npm/svelte-tag
see regarding issue on github near to the bottom is the answer from chrisward.
It makes a custom element but without shadow DOM. Found it today and workes for me.
I'm using Fullcalendar v5 in angular js, and i'm trying to make a custom event with:
https://fullcalendar.io/docs/content-injection
eventContent: function(arg) {
return { html: constructEvent(arg) }
},
The thing is that if i add:
"<div ng-repeat='user in arg.event._def.extendedProps.users' class='avatar'>"
"<p>{{ user.name }}</p>"
"</div>"
it won't render. It's like it's outside angular's scope. Can someone tell me if there is a way to construct this with angular js logic? Or i need to use vanilla js to iterate through items. Also ng-click doens't work. I tried even with triggering safeApply digest but no results.
I just want to edit the event inside calendar with the framework i'm using, and use angular events inside it to open sidebars or to make api calls.
Rendering Events
with your line <div ng-repeat it seems that you'd like to iterate through an array of events to display on your screen. If this is the case, you simply need to render the events via the 'events' parameter.
https://fullcalendar.io/docs/event-object
Regarding eventContent (the contents of an event, such as title, subtitle, img, etc)
It looks like at the minute only React JSX Nodes are supported. Vanilla JS is your only way forward.
https://fullcalendar.io/docs/content-injection
I am using a 3rd party plugin (ngx-modialog) that has a plugin architecture and I am using its Bootstrap plugin. Unfortunately there is a bug that after you use it to open a modal window, it does not remove a class from the body tag.
I can remove it myself after the user clicks the modal using jQuery:
jQuery('body').removeClass('modal-open');
But I would like to know how can I do the exact same as the above line in Angular?
I found I could do this to get a ref to the body:
let body = document.getElementsByTagName('body');
I was hoping that might expose a removeClass method. There must be a simple way to do this, so I can abide by the rule of NO JQUERY in Angular! ;)
NOTE
I am NOT looking to use [ng-class] as I have nothing I can bind to in this scenario.
To do that in Angular 4, you can use the Renderer2 class
Use the method: removeClass(el: any, name: string): void
Renderer2 is an abstraction provided by Angular to manipulate elements of your app without having to touch the DOM directly
You can import Renderer2 like this:
import {Renderer2} from '#angular/core';
Inject it in the constructor of your component:
constructor(private renderer: Renderer2){
}
Remove a class:
this.renderer.removeClass('body', 'modal-open');
As pointed out in the comments, the 'body' is outside of the domain of Angular - Angular loads its component hierarchy inside it.
So therefore I just need to fall back to regular javascript to do this:
document.body.className = document.body.className.replace('modal-open','');
Thanks to this question. No jQuery needed. But the accepted answer is the 'angular way' to do this, which is what I was after.
I want to use Bindings in Polymer Library also outside from Polymer COmponents (vie "dom-bind" of the content body of the Page). Now I have a question, is there a Concept like the "DataContext" of an Element as it is in WPF or SL in Polymer available? That means that I can define Bindings that are relative to a "DataContext" of the Element!
Example:
<div id="droot">
<my-conveyor isoccupied={{BB}}></my-conveyor>
</div>
and I have a Javascript Object like this
{
HH : {
BB : true
}
}
and I set the DataContext of "droot" to "HH" so that is derived to "my-conveyor". Is something like this possible?
I need it, because we convert or WPF/SL Views automatically to HTML.
There is currently, as far as I know, no way of doing this, but it could be possible to extend the existing data binding helpers to support this features.
Something like:
<template is="dom-context" context="{{HH}}">
<my-conveyor is-occupied="{{BB}}"></my-conveyor>
<template>