How can I programmatically/dynamically change the view? - angularjs

I'd like to have a "wizard" of sorts where the screen changes a few times during the process. I'd like to utiilze Angular's controllers for this. I can't however, figure out how to change the view that's being displayed programmatically.
It doesn't look like there's any kind of $scope.setView('/path/to/my/view.htm') I can define.

You are going to want to learn about ngView => http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngView
This way you can use $route to configure the display of partial content. You will want to declare the template option like:
$routeProvider.when('/path', {
templateUrl: '/path/to/my/view.htm',
}
Another option is to use ngSwitch => http://code.angularjs.org/1.1.4/docs/api/ng.directive:ngSwitch
For a wizard I would think that ngSwitch is less efficient but will be the easier of the two. This does sound like what you are looking for though.
"The ngSwitch directive is used to conditionally swap DOM structure on your template based on a scope expression."

document.location.href='#/yourRoute' to change the route programmatically
And if you want to use several views with 1 controller: define different routes with different views but the same controller

Related

Load view/controller programmatically

How do I, at runtime, load a view / controller?
Say for example I have a list of content like so
ctrl.pages = [{
controller:"myController",
templateUrl : "/app/view.html"
},{
controller:"myController2",
templateUrl : "/app/view2.html"
}]
How do I then load those views and controllers? Is it simply just a case of using "ng-include" or is there a better way? Libraries such as Angular Material dont seem to do it this way.
<ng-include ng-repeat="page in ctrl.pages"
ng-controller="{{page.controller}}"
src="{{page.templateUrl }}"></ng-include>
That seems like either a case for a template expanding directive, see the Angular docs here. Or if those pages represent different "states" of the application, somewhere a user might visit directly via a URL, they'd be a good candidate for ui-router.
check this plnk out.
I added a select of available views and based on the selection ng-include's src is updated.
I avoided initializing the controller(s) intentionally, you may include them.

Use controller view for email view CakePHP 2

What is a good way to use a controller action's view as an email template? Currently have have two separate views: one in ../View/Emails/html/example.ctp and one in ../View/Example/example.ctp. This is too wet and is giving me headaches.
Q. What is the best way to dry this up and use the same template for both?
Controller has a render method you may call explicitly
http://book.cakephp.org/2.0/en/controllers.html#rendering-a-specific-view
and pass a ../path/to/email/template
or you may extract a common element:
http://book.cakephp.org/2.0/en/views.html#elements

Dynamically switching template of a directive

Is possible (I'm guessing it is) to dynamically change template of a directive, depending on certain factors?
So, I see how theoretically it's possible - you can put all different templates into the $templateCache beforehand, and retrieve the one you need during directive compilation
something like:
restrict:'E'
scope:
data:'='
template:'='
link:(scope, elem, attrs)->
html = $templateCache.get(scope.template)
tElement.html(html)
However real question is, would be the right thing to do so? Will that badly affects performance? If for example directive used as a cell in a big grid?
Switching between Directives is a bad practice.
The Why:
Lets assume you have a DropDown Menu ( <select> ), and you Have set couple of directives that each one is linked to its option (by ngModel).
When the App runs,
You will start with initial directive set by the default value of the <select> property, and when you would try to replace that value, you would have to "Delete" the directive from the DOM and "Write" use a new one.
By now this should sound to you that it sound like jQuery.
The What Else should I do:
Well, you almost answered it for your self: use ng-switch.
ng-switch by AngularJS
Notes:
1) Switching between directive templates is possible (in the exact way you mentioned it, you set couple of templates on the background, and you load the one that fits the most according to the user interaction), but it sounds like you are about to type serious Spaghetti Code Which will be very difficult to maintain.
2) Performance: I can't tell if that would affect seriously on the performance of the app, but it will definitely be much harder to maintain.
3) If ng-switch doesn't fit there, You should look at this problem in a different angle.
EDIT:
Yes, It's common to do so:
And I've done that in couple of projects.
You have to pass a function to your template property of the new .directive.
Example:
templateUrl: function (elem, attrs){
return attrs["template"] == "table" ? "tableTemplate.html" : "listTemplate.html";
}
What this means : is that you have to add a so called "Support" attribute to your new directive. In this case I called it template.
It would look like so : <div new-directive="data" template="table"></div>

Me, AngularJS, and its 3 different ways to specify a controller

I'm confused by these three different ways to specify a controller.
1- I can have an include in the app/index.html file:
<script src="scripts/controller/nav.js"></script>
2- I can have an attribute in a route:
.when('/link/list/', {
templateUrl: 'view/list.html',
controller: 'navController'
})
3- I can have an attribute in a view:
ng-controller="navController"
It's quite a few. I wonder which way to go and when.
Kind Regards,
Stephane Eybert
Your (1) has nothing to do with (2) and (3).
And there are other places where you can bind controllers (e.g. a directive's controller property).
Each way is serves a different purpose, so go with the one that suits your situation.
If you have a directive and want to give it a specific controller, use the Directive Definition Object's controller property.
If you use ngView and want to give each view a specific controller (as is usually the case) use the $routeProviders controller.
If you want to assign a controller to some part of your view (in the main file or in a view or partial) use ngController.
All the above are methods for "binding" a controller to some part of the view (be it a single element or the whole HTML page or anything in between).
Im quite new too but Ill try to explain in a more layman way.
1 For each .js file you have (which may contain one or more controller defined), you need a corresponding entry into the script for #1 there. Its not the controller itself, more like to allow script to recognise that this .js file is part of the set of files to run.
2 is more like specify a state or route, which may or may not use a controller. Its much like saying how one event should lead to another. The controller may be involved in the transitions of the states/routes (ie. responsible from one state, to another) or within a view itself.
3 is for using a controller's functions within a view itself.
I've added comments to one of the answers, but aside from syntax this may is more of a design question. Here is my opinion
Firstly, (1) is irrelevant to the conversation.
(2) is the preferred approach when specifying the controller for the view as it decouples the controller from the view itself. This can be useful when you want to re-use the same view by providing a different controller.
If you find yourself using (3),consider making that area into a directive, since by specifying a controller you are indicating that it requires its own logic.

Partially apply an AngularJS directive

Say I want to create 'desktop-only' and 'mobile-only' directives that hide or show an element based on and env test. There are a dozen ways I could go about it, but a cool one would be to "partially apply" the existing 'ng-show' directive. So 'desktop-only' would be the equivalent of, and actually delegate to, 'ng-show="env.isDesktop"' but without the need to do the env test in some parent controller and put env in my scope.
Another common example would be a tabs plugin. I could write a tab directive to show and hide elements using show and hide jQuery functions, but this would lose a lot of the functionality already in the ngShow directive. Couldn't I have my tab directive extend the ngShow directive in order to get access to all that variable parsing, integration with ngAnimate, etc...
Is this possible?
Thanks
When using isolate scopes you could manually proxy some variables into the scope: $scope.current.device = $rootScope.current.device;
Appart from that, you could use the afforementioned approach to put a device model on $rootScope and have methods and fields, such as 'hasTouch' that did calls to Modernizr and similar.
So yes, this is possible.

Resources