AngularJS pass directive to direcive - javascript

I have a very common pattern that occurs, simplified it is along the lines of (pretend the all caps things are directives)
SOMESTUFF
BUTTONS
HEADER
<div ng-repeat="blah in data">
CONTENT
</div>
FOOTER
This is the same and repeated throughout the app, and will be repeated in subsequent apps. However, occasionally (particularly in the future) we will have a few pages where BUTTONS will be different but everything else the same. Or maybe CONTENT is different. Obviously, I could make each of these sections a directive and on each page put something like the above, however if I decide there needs to be MORESTUFF after FOOTER on every page I have to go through every page and add this.
Therefore, I feel the ideal setup would be one big directive, that contains each of the above smaller directives, and then be able to plug in other directives, so something along the lines of:
<BIGDIRECTIVE header="SPECIALHEADER">
And that would generate a big directive but with SPECIALHEADER in place of HEADER. Equally I could do
<BIGDIRECTIVE header="SPECIALHEADER" footer="SPECIALFOOTER">
Is this a good idea, or even possible? Does something like this exist or would I have to generate and compile the sub-directives on the fly?

Related

No DIVs created by D3 on enter() data with multiple values

Please note that it's not a question on how to get a bar. I've got that covered, luckily. It's more of a why not issue. When the reality doesn't meet the expectation, there's usually a lesson to be learned. Also, based on the awesomely helpful comments, I realized that the diagnostics were incorrect so I updated the question.
I've just started experimenting with D3. Following the examples, I get some nice graphs. Then, I tested this (just to accumulate knowledge on less usual approach with purely academic purpose).
var graphs = d3.select("#graph").selectAll("div");
graphs.data([1, 2, 3, 4]).enter()
.append("div").text(function(d){ return d; });
The number of DIVs doesn't change. That confuses me, because I'd expect an increment by 4 (if I'm creating a DIV for each such element). When I fiddle the code, it works. However, I'm stuck on how to trouble-shoot it.
I checked that d3.select("#graph") does contain precisely one element.
I've run the script from the console to avoid load order issues.
My page is a partial view rendered by Razor. All other scripts, except jQuery, which I'need to keep as it's called on page load, are removed.
...
<div id="#graph" ...></div>
...
#section style{ #Styles.Render("~/Page.css") }
#section script{
#Scripts.Render("~/Page.js")
#Scripts.Render("~/Scripts/d3.min.js")
}
I see three things in your code. First of all, using the selector d3.("#graph") refers to <div id="graph" />. You've got a sharp sign in the id of the HTML. That's why you don't see the number of elements increase - they're created into a different component. Use this, instead.
<div id="graph" ...>
An additional point's the order of your scripts. You markup is wrong because you read in Page.js before d3.min.js. If you're not getting errors because of lacking d3 in the onload of your page (which I'm assuming is in the first one), then you've got multiple references to it. This one is unneeded because you've got a global one covering it. Or you can switch the order of scripts like this and skip the global one.
#section script{
#Scripts.Render("~/Scripts/d3.min.js")
#Scripts.Render("~/Page.js")
}
Last point's about your sections. I'm assuming they're called from the layout and that this is only a partial view. If so, keep an eye on the order of rendering. Invoking the rendering of sections in partial views at different stages of the layout can create issues.

Angular UI-router nested views capabilities

I am trying to learn and understand the capabilities of UI-router with Angular 1.3.15.
I am trying to set up an application which has many views that have a header and footer directive. It also has a smaller number of views that do not need this setup, with the loaded view taking up the entire page.
Therefore, it seems I should handle this divergence "one level down", as in my diagram below. In the past, I have worked on ui-router apps with the index.html coded with the header/footer directives and a single ui-view for the other pages to load into. This time I am trying to get it correct form the start. Opinions and advice welcome.
I'm not sure what you want to know.
Yeah, you should handle the difference in templates the way you suggested: the root template should contain only the elements which appear on all states. Elements which appear on some states should go on those states templates, in the template of a parent state (if it makes sense), or in directives that you reuse in the various templates.
Instead of directives, you might want to use named views if your templates have some peatures in common, but the differences between them are not inside a single DOM element. For example, maybe all your pages have a small toolbar on top that always has some buttons, but other buttons depend on the state you are in. You can place that constant part of the toolbar in the root template, together with a <div ui-view="toolbar"></div>. The states would then define a view named toolbar with a template with the buttons they want to add.
You could make a directive for that toolbar with all the global buttons in its template and use <ng-transclude> to add the custom buttons at each state's template, but using named views seems cleaner.

How to decide when to use ngView or ngInclude?

Just trying to understand the exact difference in approaches of using ngView and ngInclude in AngularJS. When would is it correct to use one over the other? Thanks.
ngView works together with routing, and is mostly essential to an angular SPA. It's normally used to include the main content of your site, the bit in between the header and footer that changes every time a user clicks a link. Its integration with routing means changing the ngView content changes the controller too (depending on your configuration).
ngInclude is a general purpose include, you may not even need it. You'd sometimes use it inside a view to avoid repeating yourself, in the cases where several views need the same code included.

other than ng-view page loading

I am using a master page having navigation and ng-view on it, partial pages loading successfully under ng-view and with navigation of master page , but I require to load some isolated page like login.html page but not under ng-view and without master page content during route.
I am new on angular and not sure how to do this, login page loaded every time under ng-view.
Please suggest me any way to do this.
Thanks in advanced.
ng-include is your friend. see doc
here is simple way, but you should go to doc and see that there are extra options as to what can be done onload and if you want to autoscroll or do some kind of animation.
<div ng-include="'somefile.html'">
</div>
The one extra note is that ng-include is given an expression so if you have a static reference you need the extra quotes.
One of the great things about Angular is it is very flexible. Ultimately it will depend on your app and how you work. I'm not exactly certain what you are trying to accomplish but, it sounds like a job for the ngInclude directive as Dan mentioned.
You mention a login.html that excludes navigational and other main page content. Using a modal may be a viable alternative interface decision.
If you have everything built and you only want to hide part of the DOM and be done with it then, nghide or ngShow may be the quickest solution.
If there is a lot of stuff on your index.html you may want to separate those things into partials other than the ones connected directly to your routes, and use ng-include="'path/to/partial.html'" to include them. (The "''" are intentional as it likes a string.) Read the docs and experiment with the plunkr. You can do a lot of cool things with ngInclude, especially if you pay attention to its context.
If you combine the ngInclude directive with ng-switch-when, you could put together something like:
<div ng-switch="routeAction">
<div ng-switch-when="extpage" ng-include="'extraneous.content.html'"></div>
<div ng-switch-when="login" ng-include="'login.partial.html'"></div>
<div ng-switch-default ng-include="'default.tpl.html'"></div>
</div>
Where routeAction is tied to your controler which, is tied to your $route or $location.. depending on how you have things set up.

How to implement an Enterprise-grade JavaScript "framework" for web designers?

I have been tasked with improving the current mess that is our JavaScript "strategy"; we're an online shopping company and my boss has given me time to do this properly. He is very keen on keepin this modular and increase the reusability of the components.
Our HTML is being rendered with JSP and we have lots of custom tags writing out, for example, information about products without the web designers needing to worry about it.
Now, we want to do similar things with JavaScript. The web designers should be given a set of custom tags, like, say,
<foo:draggable>
... some HTML here ...
</foo:draggable>
that will wrap the HTML in a <div> with a drag bar at the top and a close button.
My idea is to mark the div with a unique namespaced CSS class name, like foo_draggable, and then put all my functions in a single JS file. That JS file then sees if there are elements with the CSS class foo_draggable in the DOM and if it finds any it will attach the required event handlers.
However, I am worried about scaling problems, and wondering whether it is a good idea to have lots of selector queries running when they quite often aren't going to be used.
The first alternative would be to initiate each draggable item explicitly but that would mean putting <script> tags all over the place. The second approach would be to not put all UI function in one file but rather just download the ones I need, but that would mean lots more HTTP requests and slower page load speed.
Has anyone got experience with this?
What about having two classnames?
<div class='foo fooDragable'></div>
<div class='foo fooSortable'></div>
You add the class 'foo' to all your elements that require javascript modification.
Your javascript has to check the dom only once for foo.
var $foo = $('.foo');
Afterwards you can search within this array which should be way smaller than the complete dom.
var $dragAble = $foo.filter('.fooDragable');
Have you considered or taken a look to JSF? I know it's a major change if you aren't using JSF yet. But there are lot of ready-to-use JSF component libaries with an ajaxical sauce, for example RichFaces, IceFaces, PrimeFaces, etc. It's almost a waste of time to create components/tags for it yourself.
Alternatively you can replace all Javascripts to use the great jQuery JS framework.
Depending on how many separate components you have, the extra overhead of running the selectors might not be a big deal. You can initialize all the components just the once, when the page is loaded. Anything that's not present on the page simply won't get initialized, and will incur no further overhead. In most JavaScript frameworks, selecting by classname (or tag name) is pretty fast. It's only the complex selectors, which aren't natively supported by the browser, that are slow.
If you have a few commonly used components, and then a set of less commonly used ones, it may be worth splitting those up. Keep the commonly used components in a single JavaScript file (minified, served with compression and aggressive caching), and load that in every page, regardless of whether it's needed or not. Caching will ensure it's only downloaded once, and it'll only be one small HTTP request. For the less common components, keep them in separate files (ideally, one per component), and add a script tag on pages that use them.
I'm not entirely familiar with how JSP works, but it might be possible to do this automatically - if a tag is included in the document, add a script tag for foo_widget.js in the document header, or something like that.

Categories

Resources