How to make proper container component using Angular? - angularjs

In the project I work on there are list "manipulation controls", like:
The parts of this controls are the same at 90% of the pages. So I'm thinking about writing "manipulation controls" Component, so I wouldn't change sizes at every page, just in Component's template if I need to (all these col-xs-*), or just copy/paste html for each input separately.
<div class="row">
<div class="col-xs-7 form-inline">
<div class="col-xs-9">
<!-- Search input -->
</div>
<div class="col-xs-3">
<!-- Type select -->
</div>
</div>
<div class="col-xs-5 form-inline right">
<sort-by ng-model="sortBy" ng-change="setCurrentPage(1);" values="{{sortValues}}"></sort-by>
<items-per-page ng-model="itemsPerPage" ng-change="setCurrentPage(1);"></items-per-page>
</div>
</div>
Is it a good idea to make such "container" component? Is there any tutorial on how to make it properly (some of the inputs might be hidden, i.e. list is small and there is no need for pagination, every placeholder, title are unique in general, so there might be many variables to pass)?
This is more or less architecture question, I'm not experienced in this, but to my mind the idea of writing such component is good. If I'm mistaken or the question isn't specific enough, please argument it.

Yes, it is a good idea to turn reusable code into components.
Yes, passing configuration variables is how you would customize it for each use case. Using ng-show, ng-hide, ng-if, ng-switch, ng-class, ng-style, etc ... there are many ways to implement the options in your template.
When you have a large number of options, it is common practice to pass them as one object. (ie. config="{foo: 'bar', baz: 'biz'}" vs foo="bar" baz="biz").

Yes, it's a good idea: that's the purpose of directives (or components, in the new 1.5x implementations): inject in your HTML some reusable components in an intelligent way.
Think if you ever need to bind a variable to your "containers": you'll be able to do it easily and with no pain at all, by using directives/components.
Alternatively, if you don't need any form of logic inside your "containers", you could use ng-include with templates to inject html in your pages, like this:
<div ng-include"myContainer.html"></div>
and somewhere in your "templates.html"..
<script type="text/ng-template" id="myContainer.html">
<!-- content -->
</script>

What you are looking for is Angular directive (https://docs.angularjs.org/guide/directive)

Related

Have my code act as a p tag and not as a link if there is no URL

I am relatively new to angularJs so I am trying to learn how to do different things. I have been trying to make solutionName act as a p tag if there is no URL input for solutionUrl1, at the moment solutionName is acting as if it is hyperlinked even when its not. Any help would be appreciated.
<a ng-href="{{::data.solutionUrl1}}" class="card__title" style="text-align: center">
<span>{{::data.solutionName}}</span>
</a>
Use ng-if of angularjs to render either one or the other:
Something like this, you most probably have to change the condition to meet your needs. You can also create a new Variable in the JS files like showLink and set this variable to true/false depending on some conditions. And then just use this boolean variable to show/hide the link with the method outlined below:
<div ng-if="data.solutionUrl1">
<!-- code to render the link-->
</div>
<div ng-if="!data.solutionUrl1">
<!-- code to render just the span without the link -->
</div>

AngularJS - Binding same scope to multiple copies of a form using ng-include

I have a simple search form which I have it included in two different pages using ng-include directive. I would like to bind them both to the same scope in such a way that when the user navigates between the pages, they'll keep seeing the same search data they've entered in either of the copies.
I have managed to implement an untidy solution using rootScope, but would like to know if this can be implemented in a proper, cleaner way?
I also used root scope slove it, my layout below:
<div id="page-header" ng-include="'views/layouts/header.html'"></div>
<div id="content">
<div ui-view="content" ng-cloak></div>
</div>
<div id="page-footer" ng-include="'views/layouts/footer.html'"></div>
<div id="toastElement">
<ul id="toastBox"></ul>
</div>
header.html bound HeaderController, the functions in HeaderController include search, login, logout, register and both working on $rootScope. Is it helpful?

Filter a directive by using a div wrapper or within the directive tag

I'm trying to go with the best approach and avoid unnecessary rendering/processing time in my AngularJS app when choosing between 2 directives to be displayed in the page inside an ngRepeat loop, want to know which is the best way:
If by setting the ng-if directly in the directive html element, like:
<div ng-repeat="element in list">
<my-directive-a ng-if="someFunction(element)"></my-directive-a>
<my-directive-b ng-if="!someFunction(element)"></my-directive-b>
</div>
Or by moving out the first <div> from the directive's template and use it as a wrapper for each directive. For instance:
<div ng-repeat="element in list">
<div ng-if="someFunction(element)">
<my-directive-a></my-directive-a>
</div>
<div ng-if="!someFunction(element)">
<my-directive-b></my-directive-b>
</div>
</div>
NOTE: The starting <div> element on each directive could be modified behave the same so I will basically take that out of the directive's html and moving it outside the directive declaration in order to place the ng-if there
What would be the best approach for this case? Are there any performance implications from doing it one way or another? Or is it just the same thing? Consider that the number of elements in the list could get really big.
They are quite the same, but you can improve performance with one-time binding, but only when element does not change at runtime (for example, let's say that it has property name, and your someFunction is like return element.name === 'John'). Angular just stop observing this function when it returns value, and watches will be deleted. There are 2 prerequisites to use this solution:
Elements properties in list does not change (if you rely on them in someFunction), for example if you rely on name property name must not change, because watcher on someFunction is note available.
When list changes or its elements properties change, you reload all list (for example, you fetch it from server again if you know that change occurred)
What you get with this? There is no watches after my-directives are drawn on ng-ifs, and when something changes, new reference is bound to list (for example, it comes from server) and everything will be redrawn, ng-ifs will run again and when will become stable (function returns value) then will be unbound. How it looks like? Like this:
<div ng-repeat="element in list">
<div ng-if="::(someFunction(element))">
<my-directive-a></my-directive-a>
</div>
<div ng-if="::(!someFunction(element))">
<my-directive-b></my-directive-b>
</div>
</div>
Two colons before expression. But be aware, that with one-time binding it's easy to mess up - you need to be sure that you test your code enough to be sure it works.

How to kill image flash in AngularJS

I'm trying to use AngularJS built-in directives to achieve some simple JS effect without writing actual js code. It actually works pretty well, except the initial flash.
I know to deal with text, people should use ng-bind instead of {{}}
But how do you deal with directives like ng-if?
Here is my code:
<li ng-if="!magazines.resolved"> <!-- add "&& isOwner" when done -->
<dl>
<dt ng-model="changeToActivation" ng-init="changeToActivation=false" ng-mouseover="changeToActivation=true" ng-mouseleave="changeToActivation=false"><img ng-if="!changeToActivation" ng-src="<?php echo base_url('public/images/system_icons/add_magazine.jpg');?>">
<img ng-click="addMagazine()" id="activated" ng-if="changeToActivation" ng-src="<?php echo base_url('public/images/system_icons/add_magazine_activated.jpg');?>"></dt>
<dd class="magazineName">Create <br> A new magazine</dd>
<dd class="publishDate">Now!</dd>
</dl>
</li>
I know it gets a bit hard to read, but it's very easy. There is a model defined on <dt></dt> tag. If mouse is over this tag, the model value becomes true; when leaves, it becomes false.
Based on this boolean model value, one or the other image will be shown.
It works like a charm, but I can see both images at the very beginning, flashing!
How to deal with something like this then?
ngCloak may help, but you should also use ng-src for the actual image source, this will prevent your site from loading the image before the model has received a value. Also when using ngCloak, you may need to load the AngularJS source at the top of your html file as it may try to load the image before it knows what to do with the ng-cloak directive.
Applying ngCloak to you dt should do the trick for you: http://docs.angularjs.org/api/ng.directive:ngCloak
Here's an example from the docs. Note that it's added in two places- the directive as well as a class. The class is only needed for IE7 support.
<div id="template2" ng-cloak class="ng-cloak">{{ 'hello IE7' }}</div>

Include behaviour inside ng-switch

I'm building a reasonably non-trivial Angular-js application for the first time and am trying to establish some intuition about how to get things done. Most things are making sense, but there's one pattern in particular that has me stumped -
Whenever I place an "include" style directive inside an ng-switch, it is ignored. I've experimented with just about every style of ng-switch, ng-include, and ng-transclude I can think of to achieve the desired behaviour, but to no avail. I haven't noticed any documentation indicating that this would be disallowed, nor any equivalent style of pattern.
Here is an example of what I have tried to do:
<div ng-switch="is_logged_in()">
<div ng-switch-when="true">
logged-in:
<div ng-include="'views/logout.html'"> </div>
</div>
<div ng-switch-default>
not-logged-in
</div>
</div>
The expected behaviour being that the logout form is displayed when $scope.is_logged_in() returns true.
The behaviour I see is that "logged-in:" is displayed, but the include isn't.
I've tried various versions of Angular-js. I've inspected the network traffic and seen that the include is in-fact being fetched, but I can't get this to work. I've had the same behaviour manifest when trying to build my own template control structures using directives.
The way I've seen most examples dodge this is by using JS in a directive to manually show/hide various sections of the transcluded content - is this really the idiomatic way to get the behaviour I'm looking for?
Thanks!
While using ng-include I always assign the path to a variable in controller.
$scope.logoutlink ='views/logout.html'
And in the view you can assign as
<div ng-include="{{logoutlink}}"> </div>
It would be helpful to post a JSfiddle link.

Resources