Avoiding ng-include while allowing flexibility in rendering sub-templates - javascript

I have a component which is treated like a "blog post" for example. A single piece of content that contains data. I've created a bunch of templates that can be rendered using ng-include in my "blog" template.
A few examples:
Blog content (title, author, etc.)
Related Posts
Author information
Email signup
(Any infinite number of possibilities)
I can't hardcode these into the template for a few reasons.
Each section needs to be able to be presented in any order (order dependent upon JSON)
All of these options need to be optional
Normally I would use some kind of foreach loop in the angular template and conditionally load each template via ng-include, but I've read this could have a major performance hit.
What's the best way to approach this using Angular 1.6.4 and components?

What about using a function to decide which template to include? This is a very generic example.
<div ng-include="vm.getTemplate(myVar)">
</div>
function
vm.getTemplate = function(myVar) {
//logic to decide template
return '../templates/someTemplate.html';
}

Related

Is it possible to create a subpage without any file?

I'm a newbie when it comes to PHP. I wrote some JS to make AJAX requests for my project and it worked well, but I don't have any idea how to convert that into PHP.
I've prepared layouts like the following:
mainLayout.php,
userLayout.php,
offerLayout.php,
In those files are some PHP and MySQL parts that build an HTML page.
In Ajax it was easy to navigate between many users using only one page and replacing some divs with data...
But a huge minus was that you couldn't have a single address reference a user profile or the offer (like mywebsite.com/user1).
Now, when I use PHP I want to achieve same layout effect.
How can I avoid creating a thousands of pages (of course even dynamically it seems to be a waste of memory IMO) like user1.php, user2.php, offer1.php, etc.
I don't know how to achieve the effect of being on a site like example.com/user277373.php without creating thousands of files but only one template.
Two solutions I see is either you use GET to parse your data:
http://example.com/?data=1736861
and than access it over the $_GET variable:
$id = $_GET["data"];
($id will be 1736861)
or you use the flight php extension, that will look something like this:
Flight::route('/id/#id', function($id){
echo "ID: $id";
});
and the URL would look like http://example.com/id/1736861. You can also use multiple variables with the flight module.
I hope this helped, Sebastian
Are you familiar with any MVC frameworks? If not, I would highly recommend getting accustomed to the MVC design paradigm. MVC = Model View Controller. From Wikipedia, a short excerpt:
A model stores data that is retrieved according to commands from the controller and displayed in the view.
A view generates new output to the user based on changes in the model.
A controller can send commands to the model to update the model's state (e.g., editing a document). It can also send commands to its
associated view to change the view's presentation of the model (e.g.,
scrolling through a document).
Two of the key components of MANY frameworks (in pretty much any language), are Routes and Templates. When utilizing a routing system, you're able to specify a template for every page loaded that matches a specific route. For instance, site.com/people/:id where ':id' can be any value in the URL, and be configured to use "person.html" for the HTML output. Note that "person.html" receives variables/data that will dynamically populate content, e.g. <h2>Hello, {{name}}</h2>
So, to clarify, site.com/people/252, site.com/people/12, site.com/people/5, site.com/people/john would all match the site.com/people/:id route path where :id is dynamic, and your system will use ONE TEMPLATE (which you specify) to display all the data. Don't forget, when that route path is met, that's only step 1. You will probably need to take that :id run some database query and pass that data into the template.
A popular micro PHP framework called Slim, might be a good starting point. Here's documentation for its way of handling Routes and Templates:
https://www.slimframework.com/docs/objects/router.html
https://www.slimframework.com/docs/features/templates.html
Slim is commonly used with Twig, a super popular PHP template engine. Here's its website/documentation: http://twig.sensiolabs.org/
And if that wasn't enough, Slim has a super handy First App Walkthrough that will show you routes, database connection, and templates: https://www.slimframework.com/docs/tutorial/first-app.html
Hope this information helps you on your journey – Best of luck!

Persistent templates (or re-using templates) with Hogan / Mustache?

Not entirely sure if "persistent templates" is what I am after, this is the first time I am using a Javascript templating engine. I am curious if there is a way of keeping the template data intact for the purposes of re-rendering a document once it has been rendered...
An example -- I define a simple template snippet:
<div id="price">Price: {{current_price}}</div>
I render it:
var template = Hogan.compile($("#price").html())
$("#price").html(template.render(price_data))
Let's say I want to update the price information every X seconds (fire a request, grab JSON and push it back to #price), re-rendering the template fails as there is no {{current_price}} any more. I could just do something along the lines of $('#price').text('Price: ' + price_data) after a succesful request but I feel this somehow makes the idea behind using templates useless.
So the question is, what is a way to re-use templates on a document? Cache the template data into a variable and re-use it when rendering or is there a more clever way?
Thanks.
You shouldn't be using a thing as its own template, you'll run into all sorts of problems (especially once you start adding mustache tags to attributes, or conditionally showing html tags, or anything like that).
Make your template its own element on the page. And do yourself a favor and use a <script type="text/x-mustache"> tag for it.

Angular.js load, process and display dynamic template obtained via REST $resource

I have an Angular app that needs to support customizable reporting. My intention is to allow the user to select one of many reports available and have a back end REST api provide the template and the data as JSON (end user can customize the template).
The app would then insert the template somehow into a "reporting" view page then put the data in the scope and Angular should compile and display the report / template.
I've looked into ng-include however that seems to support only an URL or path to a document, however I have the template text already via the REST service and I cannot use static urls or file paths, this needs to be via REST api, if ng-include accepted the template text directly that might work but it doesn't.
I've tried writing a directive, trying to call a method on the page (getTemplate()) that would load the template already fetched from the scope however my directive doesn't have access to the scope apparently.
What tactic should I use to accomplish this? A directive seems best but I'm obviously doing it wrong and completely lost in the docs and my many attempts trying to accomplish this.
You could compile the dynamic template to an element on the DOM in a controller and then in the controller have something like this:
var el = angular.element('#myselector');
el.html(mydynamichtmlfromresource);
$compile(el.contents())($scope);
I would setup your route with template with single DIV container (you could pull all the static container template in a single JavaScript file using HTMLToJS online tool or grunt task):
<section class="view">
<div id="myselector"></div>
</section>
I've tried writing a directive, trying to call a method on the page
(getTemplate()) that would load the template already fetched from the
scope however my directive doesn't have access to the scope
apparently.
Yes you are right, but there is a way to pass data from scope to directive. lets say you want to pass a var "x" from scope to directive
use this
<directive directiveVar='x'/>
inside directive, you need to use isolated scope
"scope": {
"directiveVar": "="
},
this variable will be available only in controller and postlink function, so your directive template needs to be like this
<ng-bind-html="directiveVar"/>
inside the postlink you may need to use this code snippet
$scope.directiveVar =$sce.trustAsHtml($scope.directiveVar)
References
http://docs.angularjs.org/api/ng.directive:ngBindHtml
http://docs.angularjs.org/api/ng.$compile

Getting started with Angular JS - Structure and other questions

I'm new to AngularJS and have gone through its tutorial, read some of its documentation, and I understand the main aspects. But I'd like some help in organizing the structure of my project.
Basically, I want to have a single page app. There will be a few main sections, e.g: Customers, Sales, Reports, etc. Each section will have its own pages e.g 'Add a Customer', 'View Sales reports', etc.
1) So, should I make one module for my app, with different routes and controllers for every screen?
2) Or should I have multiple modules, e.g one module for 'Customers', one for 'Sales', etc?
3) Say I have a 'Add Customer' form which has a bunch of fields. I want this form to be interactive e.g if the user selects his country from a dropdown, I want to load the cities for that country via an ajax request. Would I do this event handling within my controller, or should I make a directive for it? What if I'm only ever going to need this functionality for one form, should I still go to the trouble of writing a directive?
4) I want to build a CRUD form builder type of library, where I would add the fields that are required, and it would in return generate the add/edit/delete/list views and forms, alongwith the required form validation. Something like this:
var crud = new CrudLib();
crud.addTextbox('first').label('First Name').rules('required');
crud.addTextbox('email').label('Email').rules('required,email');
//....
crud.init();
Should I make this a module, or a directive, or something else?
(Too many questions in one question.)
1) and 2): organize your controllers and services into modules however you like. I tend to put "related things" into a separate module. E.g., a LoginCtrl, LogoutCtrl, UserService, etc. I put into a User.js file, which is a module.
3) AJAX interactions should be put in a service/factory/provider. Event handling should be in directives. (Directives may seem a bit cumbersome/overkill at times, but use them whenever you need to manipulate the DOM, attach event handlers, or reuse a chunk of HTML.)
4) You will need to write a directive if you need custom form validation. See also How can I use Angular to output dynamic form fields?

When using (only) a templating system, how should I manage CSS, javascript etc for sub-templates?

I've had this same question when working with different templating systems in different languages in the past, so first,
The general question
I want to use a sub-template to include a certain UI component which might appear in different places on a number of different pages. This UI component requires certain CSS and JS files.
I want to Do The Right Thing with CSS and JS resources, which, as far as I know and in broad terms, is to a) combine as many as possible b) minify as much as possible and maybe c) put what I can at the end of my markup so the browser doesn't have to wait for them to load before displaying content.
So, if I've got various different UI components, as well as different headers and sidebars in different sections of the site, which all require their own special CSS and JS to function correctly, what's the best way for me to manage them through a templating system so that the final markup is as small and well-organised as possible?
Specifics of my situation
I'm working on a large legacy PHP site, on which, to give the original authors the benefit of the doubt, development may have begun before MVC became really mainstream, and before there were so many choices of frameworks around to use. So there is no consistent MVC framework, no routing, no templating (no ORM either, but that particular curse isn't as relevant here).
I'm going to have to keep things ticking over, squashing bugs and adding a few new features until a complete rewrite is usable, so I'm trying to breathe some sanity into things as I go along.
The easiest place to start seemed to be the views layer, for which I'm using TinyButStrong. An example of their sub-templates can be found here, but like I said, I think this is a very general question.
Things I've considered
With a more integrated framework I'd like to be able to do something like $view->add_js($foo), but transitioning to a full-blown framework is what other people are doing while I try keep the existing codebase seaworthy. There isn't even really enough consistent organisation of files to roll something like this by hand.
At the moment the best thing I can come up with is making a DOMDocument out of the view right before it's output and manipulating <link> and <script> tags at that point. I don't know if that's a bit crazy though. Given the generality of the problem I'd like to think that there's a known sensible way to go about it.
Many thanks for your input.
It's hard for the reader to know what can or cannot be done with your code base. A common way to handle this situation would be to pass parameters to the view template, and the template can then include conditional chunks or include sub-templates based on your parameters. This does not require a full-fledged framework, a stand-alone template engine should do. If your template engine supports inheritance there is a nice pattern for handling assets in your templates - check here for example http://symfony.com/doc/2.0/book/templating.html.
Manipulating the Dom for each request to handle this kind of thing seems bit unorthodox.
What you want in this situation is some form of template inheritance; that is, technology whereby a sub-template has access to areas in a 'parent' template, and can edit or replace content in those areas. Using this ability, CSS and JS required for a component included via a sub-template can be added in to the <head> element of the parent page.
In Twig, this is achieved using named blocks. First, you create your parent template (or layout, as it's called in Twig), e.g. index.html.twig. You include in it a named block like {% block myCss %}.
Next, to create a sub-template, you begin the template with the line {% extends ::index.html.twig %}. Then, the content of a block defined in the sub-template with the same name as a block in the parent template (in this case {% block myCSS %}) will get substituted into the parent template. To append rather than replace content in the parent template, use {{ parent() }} to include content already existing in the parent.
An example of this with code is available at the link given by #Basel Shishani. I've heard that Twig is modelled after Django, and template inheritance in Django looks very similar (with the exception of using {{ block.super }} instead of {{ parent() }}. There is a discussion of how to achieve the same ends in TinyButStrong.
As a wider point, the Assetic library looks like a very promising solution for managing CSS and JS assets, in order to avoid duplication (e.g. where the same JS file is required by multiple components/subtemplates), enable concatenation and minification of assets, and more. This presentation of its features gives more details.

Categories

Resources