I would like to know which is the way to load an new component inside vue3 app instance. As far as I know its only possible to use components predefined during createApp() or via some internal trickery even after initialization but never on runtime after use.
The problem is than I cant find a way to fetch the component at runtime, via an ajax call so instead of throwing "Failed to resolve component: mycomponent" it would check the server and import the component.
Yes, I know about defineAsyncComponent and vue3-sfc-loader but none of them seem to handle undefined components. They all seem to require the definition of all the components that we will be using. Or no?
var vapp = Vue.createApp({
template: '<mycomponent></mycomponent>',
components: {} /** not defined at runtime **/,
_importUndefinedComponent: function(tagname) {
$.get('/components/' + tagname + '.js');
}
});
For now I think that it's possible to edit the internal workings of Vue, as it seems that vue already uses promises to load async components....
A usecase for dynamic components. I have an crud system with hundreds of components. I want to make quick prototypes. So this way all I have to do is just upload the component to the right folder an use it. No build step and no fancy stuff. All components are using options api. So basically it's just an Object which I will eval.
Related
I am trying to build a web app with Astro + Reactjs, but I got an issue on calling useEffect. Basically useEffect is not calling, I don't get any logs in the terminal or any warnings/errors in the terminal or in the browser.
I am exporting the function as: export default function SecondSection(){}, I changed the file extension from .jsx to .tsx, still no result. I followed all instructions from astro docs to integrate react.
I am trying to use react hooks, like useEffect/useState, but for some reasons it's not working any of that.
What can cause that issue? Thank you for your time.
The first thing to check would be to make sure you are hydrating your React component where you’re using it. In Astro, components ship zero JS by default, just plain HTML. Components will only be interactive in the browser if you add a client:* directive. This is part of Astro’s “Islands Architecture”.
To include a component’s JS you need a client directive saying when to load it. In this example the component will load its JS when the page loads:
---
// src/pages/index.astro
import SecondSection from '../components/SecondSection.jsx';
---
<SecondSection client:load />
There are different directives like client:idle or client:visible that you can use to control exactly when a user needs the interactivity. There’s more about the client directives in Astro’s docs.
I have my code as given below in app.component.html i.e. as soon as the user lands on the home screen; I want to lazy load the app-image-gallery & app-users-list and want to load them with some Shimmer effect or Loader as soon as the user reaches the viewport of that particular component. Almost every grown up site use this but this thing is kind of difficult to find for Angular.
I have read many articles on lazy loading of component on button click but haven't found this thing implemented anywhere.
app.component.html
<app-navbar></<app-navbar>
<app-image-gallery></app-image-gallery> //list of images from backend
<app-users-list></app-users-list> //users list from backend
<app-faq></app-faq>
UPDATE(2022) -
After a lot of reasearch, I found these awesome packages for Angular lazy loading of components because packages like #herodevs/hero-loader & ngx loadable are deprecated for newer versions of angular. I will also attach the link to their articles-
#angular-extensions/elements
#juristr/ngx-lazy-el
ngx-element
Articles-
#juristr/ngx-lazy-el
#angular-extensions/elements
These packages are suitable for Angular 9+ versions. I hope it helps someone. And suppose if you want to load components on scroll, On Scroll Load, this is the thing you are looking for and each solution fully tested.
This solution is been tested with angular 9 and above with ivy.
If you are using older version of angular checkout this article:
https://pretagteam.com/question/load-new-modules-dynamically-in-runtime-with-angular-cli-angular-5
Angular 9+ solution:
Before you start you should make sure that your lazy loading components are in a separated module which is not imported in your app module.
First you need to pick a container element and mark it with a template variable to render your lazy component inside it.
Something like:
<div #container></div>
And then in your component class you need to query this container using #ViewChild as ViewContainerRef:
#ViewChild('container', {read: ViewContainerRef}) container: ViewContainerRef;
Now you are ready to lazy load your component using the webpack dynamic import. which as by default available in an angular app.
Then you will need to resolve the component factory using the angular ComponentFactoryResolver after you inject it in your component constructor.
And at the end you will just render the component factory in the view reference you have prepared this.container:
lazyLoadAppImageGallery() {
import('path/to/your/app-image-gallery-component')
.then(({AppImageGallery}) => {
const componentFactory =
this.componentFactoryResolver.resolveComponentFactory(AppImageGallery);
const { instance } = this.container.createComponent(componentFactory);
});
}
After you have rendered your component you might want to pass some data to it.
You could use the instance for this:
instance.propertyName = someValue
Checkout this nice article for more infos:
https://medium.com/#ckyidr9/lazy-load-feature-modules-without-routing-in-angular-9-ivy-220851cc7751
Update
Here is a working solution with dynamic render on scroll
https://stackblitz.com/edit/angular-ivy-megwrz
If you might use lazy loading with routes, just checkout angular simple documentation
https://angular.io/guide/lazy-loading-ngmodules
You could also combine both solutions. In case you want to dynamically load a component in a lazy loaded module loaded by route.
Update since Angular v13
Since v13 ComponentFactoryResolver is deprecated. Create component does require resolving component factory. You can use the component class directly thanks to the Ivy engine. Which means instead of writing:
const componentFactory = this.componentFactoryResolver.resolveComponentFactory(AppImageGallery);
const { instance } = this.container.createComponent(componentFactory);
you could just write:
this.viewContainerRef.createComponent(AppImageGallery);
I really enjoy Vue I'm a newbie trying to use just a custom tag:
<ui-button>Learn more</ui-button>
However I get an error saying that I have to register that component. So, to solve this I used: https://v2.vuejs.org/v2/api/#ignoredElements
I tried in other frameworks too and not errors are shown but other frameworks follow different approach. Maybe is not possible to distinguish between a component and a custom tag.
custom component = custom tag + encapsulated behavior and style
Is possible to avoid this in Vue without registering my tags as components?
Update
Thank you so much for your time and efforts and please I'm not saying other frameworks are better. I just wanna avoid over-engineering and use simple custom tags to make the HTML document more readable.
You should register components globally or locally.
Global registration
Vue.component('my-component-name', {
// ... options ...
})
Local registration (in another component)
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
},
// ...
}
More information about that https://v2.vuejs.org/v2/guide/components-registration.html
For some reason I can't register new components. I got a few of them and when I try to register new one I get:
Unknown custom element: <store> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in <Root>)
This is my app.js file:
Vue.component('example', require('./components/Example.vue'));
Vue.component('register', require('./components/Register.vue'));
Vue.component('loginmodal', require('./components/LoginModal.vue'));
Vue.component('products', require('./components/Products.vue'));
Vue.component('store', require('./components/Store.vue'));
And Store.vue is basically duplicated Example.vue so no point in posting that. I tried using already created components on page like register for example and it works just fine for some reason. You should also know that I'm using Laravel where Vue is pre-included and already set up by default with example component already created.
Here is my guess: you are using the component store in one of the other components listed above before registering it globally.
This could probably be adressed by changing your registering order, but I would advise you to register them locally to each component instead.
See: https://v2.vuejs.org/v2/guide/single-file-components.html
I want to separate out the logic of my app which needs to call an OData service before the main execution can continue. I have other apps which need this behaviour implemented in the future, so if I can modularise that functionality into a component, it would be very useful.
I have Component.js for the main app, and I'd like to add a second component to be run first, which then loads the main component once the OData result has been received.
How do I load a Component, then get that Component to run the next one (in this case a UIComponent)?
It seems the sap.ui.component code automatically appends "Component.js' to the end of the name provided, so how do you have different Component files with different names?
var oComponent = sap.ui.component({
name: "MYAPP.Component2",
id: "componentId"
});
Returns error,
failed to load 'MYAPP/Component2/Component.js' from ./Component2/Component.js: 404 - NOT FOUND
Could anyone provide some example code of a UIComponent having a dependency of a Component, and the file structure of that part of the application?
You can build multiple components as separate entities and then have them listed as dependent components inside a master component for your project. In your main or master component you can list these secondary components under the metadata config's dependencies array. Each component is atomic to itself so each will have its own Component.js with routes and view path. We create nested components in this same manner and it works really well.