Multiple partial views on AngularJS - javascript

I have an AngularJS application that has a list of contents on the menu. When the user clicks on an item on the menu, the content loads on the main view. There are multiple content types:
When "1" is clicked, a video is loaded. When "2" is clicked, a PDF document is loaded, and so on. Content types may repeat and be complex.
Now, I am setting $scope.content when an item is clicked and, depending on its contentType, I'm calling a different directive:
<div class="content" ng-switch on="content.contentType">
<div ng-switch-when="video">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-switch-when="pdf">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-switch-when="...">
<...-directive content="content"></...-directive>
</div>
</div>
Now I have two problems:
When the page is loaded, all the directive templates are automatically loaded. Even if I don't have a PDF in the menu, the pdf template and scripts will be loaded.
Searching for it, I learned that directives should be tiny, not entire modules of my app.
How do I rewrite the switch above so I can comply with the best practices and load the templates and scripts only when needed?

This is exactly what UI-Router is for: Angular UI Router
Decent tutorial on scotch.io
An easier drop-in replacement for your code may be to simply use ng-if. Ng-if won't instantiate the directive until it's called. Just make sure that your directives aren't transcluding the outer div- if that's the case, shut transclusion off, or add another div to wrap them.
<div class="content">
<div ng-if="content.contentType=='video'">
<videoplayer-directive video="content"></videoplayer-directive>
</div>
<div ng-if="content.contentType=='pdf'">
<pdfreader-directive pdf="content"></pdfreader-directive>
</div>
<div ng-if="content.contentType=='...'">
<...-directive content="content"></...-directive>
</div>
</div>

Related

Angular does not work with custom html attributes

I have an imported css template written on bootstrap, and want to use it inside Angular app.
Seems like exactly custom html attributes don't react a loading from router.
Application characteristics. This is a SPA, and all of pages are loaded inside Navbar Component, with corresponding router-outlet wrapping.
Problem. Any plugin will render included data only after "mechanical" refreshing page with browser "Reload this page" button. But if I change a src for image, from plugin custom attribute, for example
data-background="assets/images/slider_1.jpg"
to
img src="assets/images/slider_1.jpg"
, it will be loaded and shown from the first time.
Example of map plugin. Doesnt show nothing.
<div class="maps-container map-widget m-b-25">
<div class="map" data-addresses="[4.4, -4.4]"
data-icon="assets/images/map-marker.png"
data-zoom="16" data-street-view="1">
</div>
</div>
Example of slider plugin. No background image.
<section class="module-cover parallax text-center"
data-background="assets/images/slider_1.jpg"
data-overlay="0.5">
<div class="container">
<div class="row">
<div class="col-lg-12">
<h1>This is title</h1>
</div>
</div>
</section>
Example of grid item for blog. Here, it should follow masonry style, but renders like strict grid.
<section class="module-cover parallax text-center"
data-background="assets/images/slider_1.jpg"
data-overlay="0.5">
You better use [attr.data]="name-of-custom-attr"
This way angular manages the use of custom html attributes correctly.

Unable to scroll to a div element using hash in Angular app

I have read here and here that a page can be scrolled to a specific element using just a hash selector and a id attr.
But for some reasons I am unable to do it in my Angular application. Can this be due to the usage of routing (angular-ui-router) in my app.
What I am trying to do is moving to a specific section of one of my page, which by the way are loaded in to a state using routing.
I have :
<div class="nav_panel">
<a class="nav_links" href="#footer">Footer</a>
</div>
and
<div class="homeFooter" id="footer">
<div class="social_icons">
<span class="gplus"></span>
<span class="fb"></span>
<span class="twitter"></span>
<span class="whatsapp"></span>
<span class="youtube"></span>
</div>
</div>
on the same template.
Is there a way I can make it work with routing (if at all that matters) as well or am I doing something wrong here ?
Based on this answer, you can add the _targetattribute to the <a>tag.
For your need, value on _target is self. It's an attribute compatible with all recent browser, that will redirect you to the link in the same frame as the user click (useful for SPA e.g.)
Go to the footer
<div id="footer">Welcome to the footer</div>

Angular switch Outer Div based on boolean

I am using Angular 1.4.7 and need to do the following
<div ng-if="varIsTrue">
<div ng-if="!(varIsTrue)" my-custom-directive>
A lot of content
</div>
So basically, if the div is set only the proper div shows up. I tried do a few variations of this with ng-if and ng-show but I believe because how the browser renders the dom it is messing it up with the multiple divs, but that is the concept I am going for. Does anyone know how I can accomplish this?
You cannot do this you should have 2 closing tags
<div ng-if="varIsTrue">
</div>
<div ng-if="!(varIsTrue)" my-custom-directive>
A lot of content
</div>
or you will have to switch in my-custom-directive

website gets slow when huge amount of data is being loaded

I have a internal team website build using python django and angularJS. The website works fine when there is low data/ content on it.
When the website gets scrolled and more data is loaded. It becomes slow.
The major problem occurs when we try to open any modal or try to write text in the textarea. The text lags while writing and modal open very slowly.
I have used nested ng-repeat there are 5 nested ng-repeat.
<div ng-repeat="x in xyz">
<div ng-repeat="y in xyz">
</div>
<div ng-repeat="img in xyz">
</div>
<div ng-repeat="y in xyz">
<div ng-repeat="z in xyz">
</div>
</div>
</div>
Above is the example of the structure being used in the website.
The above snippet repeat itself around 100 times thorughout the page.
These are having images, forms, text, input , user tagging like facebook.
ngCacheBuster,ui.bootstrap, ngTagsInput, ui.mention,monospaced.elastic these are the external library being used in the website.
the website is built using bootstrap.
Is there a specific reason why the website becomes heavy.
each size of the image is around 100kb on an average.
really? the page loads slow when there is alot of data? :D
anyway the most simple method to speed-up heavy data apps is to conditionally load and render parts of it, for example:
<div ng-repeat="x in bla" ng-click="showL1 = true">
<div ng-repeat="y in boo" ng-if="showL1 === true">
//more...
</div>
</div>
on the other part is double check your architecture, since there is a very limited amount of data a person can take from a page and therefor start thinking about tabs and paging
Maybe u need use some function in your controller that will load some part of all data for user.
For example:
app.constant('range' , 10);
app.controller('example', ['$scope', function($scope) {
$scope.loadRangeData = function(range) {
//your way of loading data with using range
}
}
]);
and after u can use ng-repeat as
<div ng-repeat="x in loadRangeData">
but best way it's finding answer in your django maybe

AngularJS content in HTML loaded through JS doesn't work

I am loading an HTML file through JS, this file is containing AngularJS content which doesn't work.
<div ng-app="MyApp.firstElement" ng-controller="ControllerOne" id="firstElement">
AngularJS content
</div>
<div ng-app="MyApp.secondElement" ng-controller="ControllerTwo">
AngularJS content
</div>
<script src="loadContent.js"></script>
loadContent.js:
$(document).ready(function() {
$("#firstElement").load("includedContent.html");
})
includedContent.html:
<md-sidenav>
<md-content>
...
</md-content>
</md-sidenav>
As you can see, I have a ng-app in each div. The angular scripts & css are included in the page. But the loaded angular content isn't working.
The only way I found to make it work, is to directly paste the code from includedContent.html into the main HTML:
<div ng-app="MyApp.firstElement" ng-controller="ControllerOne" id="firstElement">
<md-sidenav>
<md-content>
...
</md-content>
</md-sidenav>
</div>
<div ng-app="MyApp.secondElement" ng-controller="ControllerTwo">
AngularJS content
</div>
<script src="loadContent.js"></script>
It does not work that way.
1/ You just need one ng-app attribute (ideally on your html element)
2/ If you want to load a template you should use directive and not load it using external .js file.
3/ Try not to use Jquery and stick to Angular. What's the point in having Angular when you want to mainpulate DOM using Jquery
Have a look at https://docs.angularjs.org/guide/directive and https://docs.angularjs.org/guide/bootstrap.
When reading about directives have a look at 'directive definition object' properties ex. template/templateUrl (that's where you can get you template) and compile post funnction (aka. link function) that will allow you to interact with your element which is a Jquery object (or JqLite object if you don't have your Jquery loaded before angular).
No need to load HTML using JS. HTML can be loaded in angular way using "ng-include='PATH_TO_FILE'" built in angular directive
<div ng-app="MyApp.firstElement" ng-controller="ControllerOne" id="firstElement" ng-include="'includedContent.html'">
AngularJS content
</div>

Categories