How to lazy load part of template in Angular 2? - javascript

I've an Angular 2 component, which contains multiple sub-components. For a few of them it's quite expensive to load them and sometimes it is not necessary to load them at all. For example if the user is not scrolling that far.
Anyway, I know how I can lazy load routes, but is there a way of lazy loading a template? Like only if a element is in or close to the Viewport?

There is no way to lazy load templates. What you can do is to lazy load modules. How to manually lazy load a module?
If you use this with ViewContainerRef.createComponent() (see Angular 2 dynamic tabs with user-click chosen components for an example) to dynamically add the components that you only want to show if the users scrolls far enough, it might work (not tried myself yet).

You can segregate or group sub-components to be displayed into smaller components to be loaded together.
To reduce the time to load,
1. try to use smaller templates inline into component file.
2. Use *ngIf directive in your template which can avoid rendering of the template and component instance is not created as such. However, take note that if you're using *ngIf it is better to use only is the DOM is not refreshed fequently, else you may create DOM and use the component by binding it with [hidden] attribute of the DOM

Related

Angular: How to do the Components Architecture the right way?

I'm currently trying to create a Angular-Webpage for a Uni-Project. Therefore i've built up a Webshop-MockUp with several different Pages like
Startscreen
Productscreen
Register/Loginscreen
Shopping-Cart Screen
Order-Screen
and Profile-Screen.
But as I'm now trying to develop the Webshop with Angular, I'm not quite sure, how the Architecture of the Component-Concept of Angular will fit to my needs.
As long as I understand for now it's working like that:
You create a Page with several (reusable) Components which all define different areas of one page.
For the example of the Startscreen, i've created the components:
hero-banner
header
filtering
product-overview
shopping-cart (will be shown on the right side)
These 5 Components can then be added to the app.components.html to show the first page.
But now I have no idea, how to create the other 5 pages and display them inside the app.component.
I've heard about the Routing to switch between components..
But does that mean I have to create one parent-component for every page where I tipe in these different components I've been creating?
And if so, what do I write into the app.component.html if I can Route between the different components anyways?
I just got a big knot in the head right now and I really hope you can help me out here!
Thanks in Advance!
Yep parent component for each page to act as manager component to talk to services, get data, and pass it down to dumb components and handle events from child components. Make your children dumb. This is known as container-component.
Yep learn routing. Also lazy load whenever you can but you can refactor this in later.
<router-outlet></router-outlet> goes in app.component.html.
Possibly something like
<app-navbar>
Text to display via ng-content
</app-navbar> <!-- Common to all routes/pages --!>
<router-outlet></router-outlet>

Get HTML from Vuetify components without posting it on the dom

For my own project I would like to fetch HTML code from multiple Vuetify components. Not as a HTML string, but really as a DOM element that can immediately be appended to the body. I want this so that I can use these components in a non Vue environment.
Is there any way I can accomplish this?
I'm not entirely sure what your use case is for this. If you could elaborate on what you're trying to achieve, I could likely give a better answer.
I've had some similar requirement in the past, where I needed to access the entire HTML content of components/sub-components.
How I did this was by rendering the components in an iframe. From there, you can access and modify the mounted iframe DOM.
I can't find the source code on how I did this but perhaps concept/approach could serve as a starting point.
From a cursory internet search, I found this link https://jsfiddle.net/ohznser9/ with a JS Fiddle demonstrating a i-frame component that takes Vue components as a slot.
I'd imagine you could extend this component to add functionality to modify or extract elements from the DOM.
Perhaps you could load the iframe invisibly, grab the DOM elements from that and do what you wish with them

Hiding parts before the page components loads

The very unpleasant situation arises when the page loads before some parts (fonts, necessary css files) are loaded.
I see on some sites, they hide some parts before the page components loads.
For example:
I don't want to put a preloader in the page. Is there just a tactic or any other solution for the problem?
These pages use a javascript framework such Angular, React, or Vue.
They use something called a lifecycle hook. I'm most familiar with Vue.js, but there are different ones depending on when they are called/what is loaded.
They more than likely use a before mounted & mounted lifecycle hook which performs actions until an item is fully loaded, then performs different actions.
If you don't use a library, and are looking to - I'd recommend Vue.js ecause you don't have to install/learn node.js to use it on a page, only need a CDN, and the link I used below will show you how to prevent your page elements from being viewed before they are loaded.
https://v3.vuejs.org/api/options-lifecycle-hooks.html
https://angular.io/guide/lifecycle-hooks
https://reactjs.org/docs/state-and-lifecycle.html

What is the best way to ensure a component's client lib files only load on the page when the component is present?

I'm new to AEM. Currently we have one template for each page on our site. All components have the category "project_name.components" and I am calling the client libs in a header file with:
<sly data-sly-call="${clientLib.css # categories='project_name.components'}" />
<sly data-sly-call="${clientLib.js # categories='project_name.components'}" />
However, I have a breadcrumbs component that isn't on every page, but, as expected, the client libs files for it are showing up regardless and causing some issues with the existing default breadcrumbs's styles/scripts.
I have given the new breadcrumb component a test category name of "project_name.breadcrumbs". Is there a way to use this category name in some type of an if/else statement in the same header file that will only call the breadcrumb client lib files if the breadcrumb has been dragged onto the page?
A few thoughts:
The easiest way is to include the client library as part of the component that uses it rather than including it somewhere else. The downside of this is that the CSS you may want to load early in the HEAD section of a page won't be present until somewhere in the BODY.
If your CSS styling is impacting things it shouldn't, then the CSS styling needs to have sufficient selectors so that it won't break things to which it shouldn't apply. Perhaps you can add a class to the breadcrumbs and make all the styling only be applied to stuff under a tag that has the class. If you changed the CSS this way, it wouldn't negatively affect pages when they don't use the breadcrumb (though it could have a downside of bloating your page footprint if it isn't something that will be loaded and browser cached to be used in the future).
Otherwise, you could add logic that runs at the page level that will examine the node and see which components are included and then add conditional logic to only add the client library when the page is using the component. But that is more back-end work. So you can add the if/else statement as you suggested, but it is up to you to write the code behind it--there is nothing built-in that will conditionally do that check to my knowledge.

Material Design Lite JS not applied to dynamically loaded html file

I want to unify the navigation layout for my website, so I created a separate html file that holds the code for the navigation. I use a JS to load the file dynamically:
$("#navigation").load("/navigation/navigation.html", function() {
$.getScript('/material.min.js');
});
The problem is that the material.min.js does not get executed for the dynamically loaded components inside this html and I lose some crucial functionality. How do I fix that?
Check if the componentHandler is loaded, and try to upgrade the elements after load.
if(!(typeof(componentHandler) == 'undefined')){
componentHandler.upgradeAllRegistered();
}
How the Component Handler works
In short this goes over all registered components. Queries for all nodes with the provided CSS class. Loops over those and instantiates them one-by-one. When the upgrade is done on a node, the upgraded object is added to the dataset. This object contains a comma separated list of component classAsString properties to identify which upgrades have been done.
From the official docs:
Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function.
So loading the material.js script again will not execute it. But you can do some experiments with upgradeElements by applying it to the whole loaded markup or to particular elements.

Categories