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);
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 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.
I want to create an in-repo addon to make certain modifications (styles, templates, etc.) to an existing ember app in an encapsulated way, but I'm having troubles overriding the templates.
Right now, I'm trying to override an existing component template with the template from a component with the same name in the in-repo addon. My code looks something like this:
// my-app/app/templates/components/foo.hbs
<h1>Some headline<h1>
// my-app/app/lib/my-addon/app/templates/components/foo.hbs
<h1>A different headline<h1> // -> this never shows up
I've tried a lot of switching around the template structure (like putting it in /addons or /app and linking to the template in different ways, but without success. My problem is that ember never uses the template from the addon.
If the component within the addon has a different name, like foobar.hbs, I can call it without a problem.
I'm currently looking through the source code and docs, trying to make sense of this. Is this even accomplishable the way I imagine it?
Thanks a lot!
You'd have to create the component in your ember app which, initially, will mean the component renders as nothing as it's a brand new, empty component. Then you'd dig into your node_modules, find the component file and template and copy over what you'd need to work with.
Here's an example. While working with ember-cli-jsonapi-pagination, I need to customize the paginate-collection component:
I created the component in my application.
I looked at the source: https://github.com/BookingSync/ember-cli-jsonapi-pagination/tree/master/app
In components/paginate-collection/component.js I copied over the component code, but you should be able to import it as well.
In components/paginate-collection/template.hbs I modified the template as needed.
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.
I'm having an issue thinking about the best way to architect a React app with multiple pages/views (still a SAP).
Let's say we have a simple app with 4 major sections (pages): dashboard, users, stats, comments. Each section has different components in it (think react components). For example, the comments section would have a hierarchy like so:
CommentsSection
- CommentsQueue
-- Comment
--- Text
--- Buttons
- CommentsApproved
--Comment
--- Text
--- Buttons
In a framework like angular for example, the 4 main sections would be split into partials, and loaded in an ng-view upon request, with their respective components inside. When landing on the homepage, the app would only load the dashboard view and upon the user clicking on a nav item, the selected route (i.e. app/users or app/users/:id) would trigger and the app will load the required "template-view-partial" (without a browser refresh).
Now in terms of React, how would this occur? it seems like ALL views and ALL their components would need to be available in a browserified JS file and the app can then update the DOM.
This seems terribly wrong, as we'd be loading all sections in the first load, even if the user doesn't ever need to get to that section. Granted, we could split it with routes on the server, and only serve the components for the page based on the route, but that would require a browser refresh, where as in Angular for example, it would happen without a browser refresh as the view is loaded asynchronously.
The question is, how can this asynchronous loading happen in a React-based app?
I think there's a few different ways in approaching this, I'll explain the approach that I am currently using for my work and side projects.
Instead of using browserify, we use a module-bundler called webpack (https://github.com/webpack/webpack). What's great about webpack is that it's like Browserify but can split your app into multiple 'bundles'. This is great because if we have multiple components/views, the user would just download the features they need for that particular view without having to download everything initially. It allows react-components and their dependencies to be downloaded on demand.
Pete Hunt wrote an article that goes into depth on the benefits of webpack when using it with React (including how to async load react components), and how it is similar/different to Browserify and modern build tools like Grunt/Gulp: https://github.com/petehunt/webpack-howto
I have described one solution using webpack here : http://blog.netgusto.com/asynchronous-reactjs-component-loading-with-webpack/
In essence :
use require.ensure([], cbk) to define code chunks; in the cbk, load your packages synchronously using require()
in your host component, load your asynchronous component in componentWillMount(), and set in in the host component state.
use it in the host component render, when defined on the state