AngularJS partials with URLs in directives - best practice? - angularjs

I quite like how angular-ui has created ui-routes, which provides named routes (among other things).
Though likely a simple directive to write—a wrapper for ui-view—I am not sure if it is best practice.
<div ui-view2="foo.html" class="span12">
Foo haz bar
</div>
With the following logic:
if `foo.html` is file: contents of foo.html
elif `$scope.foo.html` exists: contents of `$scope.foo.html`
else: contents defined in view, i.e.: "Foo haz bar"
What do you think, would this kind of setup be within the realms of best-practice?
BTW: Is there anything like this already?

You can use ng-switch
<div ng-switch="page_name">
<div ng-switch-when="foo" ng-include="'partials/foo.html.html'">
<div ng-switch-when="bar" ng-include="'partials/bar.html.html'">
</div>

You can also use ng-if if your logic doesn't fit into a ng-switch:
<div ng-if="first_condition">something</div>
<div ng-if="!first_condition && second_condition">something else</div>

Related

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?

How to make proper container component using Angular?

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)

how to use one ng-controller within another ng-app and controller in angular.js

I am new to Angular.js and want to use one ng-controller within another ng-app and ng-controller like this so that I will be able to use the code before I used on the other pages as well.
Please help me out and correct me if I am wrong anywhere.
<div id="divFriendList" class="container" ng-app="friendModule" ng-controller="friendController">
<div id="module2" ng-app="cardsModule" ng-controller="CardsController">
<div ng-repeat="card in cards></div>
</div>
</div>
I am rather new as well, but I believe a way to do this would be to declare a dependency in your module. For example, angular.module('friendModule', ['cardsModule']);. Such an example can be found here. For more about modules and a tutorial on angular you can visit W3Schools.
As for your code, you're missing the closing quotation in <div ng-repeat="card in cards>. Further, you are asking ng-repeat to iterate each card in cards, but you have not defined what cards is. Therefore, you'll want to change
<div id="module2" ng-app="cardsModule" ng-controller="CardsController">
to
<div id="module2" ng-app="cardsModule" ng-controller="CardsController as cards">.
Additionally, you will not get any information displayed if you don't ask for an output such as {{card}}. I would also consider declaring your ng-apps before hand and not when they're needed - but I'm unsure as to the efficiency of this.
What I would update as:
<div id="divFriendList" class="container" ng-app="friendModule" ng-controller="friendController">
<div id="module2" ng-app="cardsModule" ng-controller="CardsController as cards">
<div ng-repeat="card in cards">{{ card }}</div>
</div>
</div>
Hope that helps.

Add another custom interpolator in Angularjs

I still want {{1+2}} to be evaluated as normal. But in addition to the normal interpolator, I want to create a custom one that I can program to do whatever I want.
e.g. <p>[[welcome_message]]</p> should be a shortcut for <p>{{'welcome_message' | translate}}</p>, or <p translate="welcome_message"></p>. That way, i18n apps would be much more convenient to write.
Is anything like that possible? I'm currently going through the angular.js source code, but the interpolation system looks pretty complicated(?). Any suggestions?
I created a directive that regex-find-replaces it's innerHTML. Basically, I can rewrite any text into any other text. Here's how I did it:
How do I make angular.js reevaluate / recompile inner html?
Now all I have to do is to place my directive-attribute, "autotranslate", in one of the parent elements of where I want my interpolator to work, and it rewrites it however I want it! :D
<div class="panel panel-default" autotranslate>
<div class="panel-heading">[[WELCOME]]</div>
<div class="panel-body">
[[HELLO_WORLD]
</div>
</div>
becomes
<div class="panel panel-default" autotranslate>
<div class="panel-heading"><span translate="WELCOME"></span></div>
<div class="panel-body">
<span translate="HELLO_WORLD"></span>
</div>
</div>
which does exactly what I wanted.
I don't think that's possible, but if you really want to save some characters you could create a function on your rootScope called t, then call it within your views:
<p>{{ t(welcome_message) }}</p>

web scraping tool or library that automatically finds text content without rules set

Is there a web scraping tool or library that auto-detects repeating HTML blocks and scrapes the text content inside the blocks, thus removing the need for human to manually input the rules - CSS selectors or xpath to find the content?
This is based on the assumptiom that modern content website is generated dynamically by server-side languages such as PHP or Python. The content is almost always rendered by a for loop in the template, hence the repeating HTML blocks can always be found. An example:
<div id="content">
<div class="blog entry">
<div class="title">
<h1>1st post</h2>
</div>
<div class="content">
<p>...</p>
</div>
</div>
<div class="blog entry">
<div class="title">
<h1>2nd post</h2>
</div>
<div class="content">
<p>...</p>
</div>
</div>
<div class="blog entry">
<div class="title">
<h1>3rd post</h2>
</div>
<div class="content">
<p>...</p>
</div>
</div>
</div>
Libraries like bautiful soap and scrapy rely on human to input the rules before the scraping can be carried out. They are not what I want.
Haven't used it, but heard about scrapely:
Unlike most scraping libraries, Scrapely doesn't work with DOM trees
or xpaths so it doesn't depend on libraries such as lxml or libxml2.
Instead, it uses an internal pure-python parser, which can accept
poorly formed HTML. The HTML is converted into an array of token ids,
which is used for matching the items to be extracted.
Scrapely extraction is based upon the Instance Based Learning
algorithm and the matched items are combined into complex objects
(it supports nested and repeated objects), using a tree of parsers,
inspired by A Hierarchical Approach to Wrapper Induction
You might want to look at my scraping library. It doesn't work automatically nor does it detect repeated parts. But it comes close, since it doesn't need rules at all and instead uses templates, which you can get directly from the html you have.
E.g. with your example above, the template to read all the posts in 2 arrays is:
<div id="content">
<div class="blog entry">
<div class="title">
<h1>{title:=.}</h1>
</div>
<div class="content">
<p>{content:=.}</p>
</div>
</div>*
</div>
You may try HTQL:
import htql;
a=htql.Browser();
p,b=a.goUrl('http://channel9.msdn.com/Blogs/Vector/Announcing-BUILD-2012');
htql.query(p, '&html_main_text');
p,b=a.goUrl('http://stackoverflow.com/questions/tagged/screen-scraping');
htql.query(p, '&html_main_text');

Resources