Angular Web Architecture using nested components and hiding them using ng-hide - javascript

I am developing an application using Angular 1.X.
There is a component that is used across three pages.
I have several nested components into a main component. However there are two components that will only show on one page. I am currently ng-if(ing them) and was wondering if this is a bad option.
<!-- Component 1 -->
<div class="wrapper">
<div ng-if="showChildren">
<component2> </component2>
</div>
<!-- more code goes here -->
<div ng-if="showChildren">
<component3> </component3>
</div>
</div>
On the required page I would add in the controller
<component1 showChildren="true"></component1>
The code works, it gives no errors on page or in console.
Even though there might be other solutions for this, is there anything about this that is actually bad design/implementation?

This is mostly a matter of preference, as there's nothing inherently wrong with your solution.
Just a couple suggestions though:
If you are hiding all the children of the div.wrapper, why not apply the ng-show to the wrapper itself?
Since it seems that the value of showChildren won't change, why not use ng-if instead, and simplify the DOM? ng-show still generates the hidden DOM elements and uses styling to hide them, while ng-if will simply not generate them.

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>

Implement different layouts for a (part of a) web page

I want to implement a coding playground. At the moment, I use flex-box to define the position of different panels. Here is a JSBin, and its html part:
<div class="flex-box">
<div class="col" id="html-panel">
<p>html</p>
</div>
<div class="handle">
<div class="handle-inner"></div>
</div>
<div class="col" id="css-panel">
<p>css</p>
</div>
<div class="handle">
<div class="handle-inner"></div>
</div>
<div class="col" id="js-panel">
<p>javascript</p>
</div>
</div>
(to make it a playground, I add textarea inside each panel (e.g., html-textarea in html-panel), and combine the content of the 3 textareas to return an output. The playground reacts to every change to the content in textareas: I choose to use an AngularJS controller to do so, rather than JQuery event handlers.)
Now, I am wondering how to realise different layouts without repeating too much code. Like Liveweave proposing 4 layouts (see right bottom corner) to users, I want to propose displaying for example
horizontally the 3 panels as what looks like at the moment
vertically the 3 panels
1 on the left and 2 on the right
2 on the left and 1 on the right
So what's the best approach/structure/tool to implement this?
To share maximum, should we realise this with 1 common .html, 1 common .js and 4 .css files? Then, we just need to choose different .css file for different layouts?
Based on some research, this certainly can be done by nested views / UI-Router / AngularUI / Angular JS. And we will be able to define one html file per layout.
But I will first go for what #DCR suggested: by only JS and CSS. Because it is simpler, also because JS allows us to inject html, e.g., by innerHTML. Therefore, I could inject 4 html strings for 4 layouts. Inside the 4 html strings, there could be same class names, which enable some sharing of styling in CSS and functions (eg, splitter-dragging) in JS.

How to lazy load part of template in Angular 2?

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

AngularJS: Tab panes vary in HTML markup, I want them to be created dynamically and filled with data provided by factory service

I'm building a tabbed interface for displaying posts from various social networks (timelines) but not all tabs will have the same HTML markup. My factory service is returning JSON response so that part is fine.
Also, a sidebar contains tabs onto which I put ng-click for opening appropriate panes.
Now, I'm wondering if I should proceed with creating a custom directive to reside inside my tab-pane wrapper:
<div class="tab-pane">
<div timeline=""></div>
or
<timeline></timeline>
</div>
If so, I'm unsure whether $compile is the right approach? I've read that it is rarely used but it seems to me that it would allow me to dynamically decide which custom directive template to use, based on the clicked tab.
If there is a better approach to the solution, let me know. I'm really new to AngularJS but I'm eager to learn it, and learn it properly, applying best practices whenever possible.
The easy way might be:
<div class="tab-pane" ng-repeat="tab in tabs" ng-switch="tab.network">
<div ng-switch-when="Network_A">
/* Template for Network A here... */
</div>
<div ng-switch-when="Network_B">
/* Template for Network B here... */
</div>
<div ng-switch-when="Network_C">
/* Template for Network C here... */
</div>
</div>
So, you will need to add a network attribute to the tab objects, which tells what is the type of the social network.
Using directives might be a more efficient solution, but also more complicated.

$(this) doesn't work in angularJS

I am making a chrome extension with angularJS, now I have a problem.
I want add some button in my popup page, and I want when button is clicked, it's ancestor node disappear, here's my code.
in popup.html
<div class="deadline">
<div class="btn-group">
<button class="btn" ng-click="removeDeadline()">complete</button>
</div>
</div>
in controller.js
$scope.removeDeadline = function(){
$(this).closest(".deadline").remove();
}
I don't know why that doesn't work.
Please help me.
First, $ is a jQuery function--did you include jQuery in your extension? If not, angular.element is the function for the built-in "jQuery Lite" that AngularJS ships with.
Secondly, accessing a DOM element from inside a controller action is incorrect form when using AngularJS: Angular is all about views that automatically reflect the state of models (via the $scope). For example, the snippet you showed would be more properly written as:
<div class="deadline" ng-hide="hideLine">
<div class="btn-group">
<button class="btn" ng-click="removeDeadline()">complete</button>
</div>
</div>
$scope.removeDeadline = function(){
$scope.hideLine = true;
}
Take this quote from the FAQ to heart:
Stop trying to use jQuery to modify the DOM in controllers. Really. That includes adding elements, removing elements, retrieving their contents, showing and hiding them. Use built-in directives, or write your own where necessary, to do your DOM manipulation. See below about duplicating functionality.
If you're struggling to break the habit, consider removing jQuery from your app. Really. Angular has the $http service and powerful directives that make it almost always unnecessary. Angular's bundled jQLite has a handful of the features most commonly used in writing Angular directives, especially binding to events.

Categories