Controller is not a function got undefined, http.post request - angularjs

I am having trouble with an instance of a controller.
I have a simple navigation tree using this module:http://nickperkinslondon.github.io/angular-bootstrap-nav-tree/test/bs3_ng120_test_page.html
I added a double click function on any leaf, and a directive that compiles, and opens a window using this module: http://codepen.io/m-e-conroy/pen/cFKkG
The window contains a few tabs, and one of these tabs must contain another navigation tree, just like the first one but with different data.
I am also using http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/ so I can have multiple app on the same page.
Problem is, the second navigation tree that must be loaded doesn't work. I am declaring it, in the html sent this way (moduleAbn is a variable contained in the first .js loaded at start, referecing the module App1):
<script> moduleAbn.controller('AbnTestController2',['\$scope','\$http','\$timeout','\$compile',function(\$scope,\$http,\$timeout,\$compile){
...}]);</script>
<div ng-module='App1'> <div ng-controller='Controller2'>
Doing this, the console shows the famous Controller2 is not a function, got undefined.
The weird thing is, if I declare it with the name of the first navigation tree controller
<div ng-module='App1'> <div ng-controller='Controller1'>
Navigation tree appears, with the same data as the first, but seems to work independently from the other.
I really don't know how do get this working with different data from the first tree...
If I am not being clear, english is not my mother tongue so I can get more specific if you have any questions ;)
Cheers!

You should rename AbnTestController2 to Controller2 when defining it or change it's name in ng-controller= from Controller2 to AbnTestController2.
Second thing you need to check is that App1 has module AbnTest as dependency:
var App1 = angular.module('App1', ['AbnTest'])

Related

Accessing components from within a different component

Using Angularjs 1.5, I have been having trouble making a D3.js graph that's defined in one component display on a page that relies on a different one. I'm new to Angular, and while I think the answer is buried somewhere in the official documentation's example of a component tree, I wasn't able to completely follow the logic.
My goal is to make the graph defined in graphController, and make it appear as accessed by requests.template.html.
Trying to inject it into requests.component like I would a directive gave me an unknown provider error
I inherited the setup from someone else (and would prefer to leave the protect structure the way it is), and it more or less looks like this:
requests.module.js
angular.module("requests", []);
requests.component.js
angular.module('requests').component('requests', {
templateURL: 'Bindings/Templates/requests.html',
controller: function requestsController($scope) {
[code]
}
}
requests.template.html
//where I'd like to be able to access the controller from the graphs component
graphs.module.js
angular.module('graphs', []);
graphs.component.js
angular.module('graphs').component('graphs', {
templateURL: '/Bindings/Templates/graphs.template.html',
controller: function graph() {(code for d3 graph)};
}
graphs.template.js
{{$ctrl.graph()}}
//this page is just a placeholder to see the graph until I can view it on requests' page
Any help you can give or ways to think about how I should thread this controller call through would be great. Thanks!
If you are wanting the graph to display in the requests component then you can just insert the component element tag within the requests template. For example, in the Bindings/Templates/requests.html insert:
<div class="stuff-to-wrap-graph">
<graphs></graphs>
</div>
Once you have created a component, think of it like a unique html element that you can insert anywhere, including within other components. You would normally only want direct access to the controller of another component if it was a tightly coupled child of a parent, eg. an individual tab within a tabs component that needs to talk to the parent tab container.

Which controller is triggered by widget?

I have a small angular application which was written by a third party and I need to rearrange its layout (e.g. move a search form from the main body to the top menu bar).
Is there a way to determine which controller is triggered when a widget is active? Digging through source is OK and I'm doing it right now. However, I'd prefer something along the lines of a debug message
Widget [widget id] triggered [controller id]
Two ways to figure out the controller:
Check the ng-controller directive in the said HTML.
If you are using ng-route, then find the page URL in your code. Controller class can be defined when specifying routes.
Hope this helps.

Can I place ui-view on the body tag?

I'm working on an app whose header's styling and UI options will change depending upon the state a user is currently in. For example, if a user clicks the Upload, Edit Profile, Create Playlist or Create Gallery buttons in the main menu, this will cause the following changes to the header:
the header's background to change color
the site logo will have CSS3 animation applied to it to make it slide into a new position
a specific message (depending on what state the user is in) in a word bubble will appear next to the logo
a Cancel button will manifest on the right edge of the header
This means there will be no static element on my site so logic tells me that I should place ui-view in my body tag thus making it look like this:
<body ng-app="app" ui-view>
I have never seen that used before anywhere so I've my doubts. Any ideas?
I'm not sure if this will or will not work technically, but I believe you should avoid it because:
It would require all your templates to include an outermost <body> tag which makes them less reusable
It's generally an unusual thing to do, and that comes with a cost, and I see no particular benefit to this, so IMHO the cost/benefit analysis says stick with what is conventional: use <div>s.
I suspect this may in fact work, but typically the tag with ng-app stays in place for the entire lifecycle of the app. There's a chance you may hit some weird errors if you swap out the tag containing ng-app. Thus many people put ng-app on the very first <html> tag and call it done.
But it's your app and the effort to try both approaches is very low, so just try them out and see (and let us know what you learn). I don't think you need to wait for stackoverflow answer from authority to test 2 slightly different HTML structures with your app.
No, please do not do that!
Having ui-view inside of the body tag may render many JS plugins/libraries unusable, especially in case if they dynamically add some HTML tags to document.body. In such cases, navigation to another view will reinitialize document.body and thus disregard previously added HTML tags.
E.g. this is the case with Firebase and Angular.js (AngularFire). I hope everybody who has come across the error
Uncaught NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
will get to see this post. Just make sure you haven't added ui-view attribute to your body tag.

$compile is only properly inserting my template the first time that I run it

http://embed.plnkr.co/SPGNLd0bcmo2Xt2TAZcB/preview
Here we have a list of personnel information cards. If you click on one, the directive triggers a template to be loaded between that row and the row before it. My problem is that it only works once!
I believe that my problem lies somewhere in my compile statement, but I'm not sure:
$compile(controller.former)(scope);
What honestly baffles me is that even if you just click on the same card over and over again, ignoring all the others, it still just loads the one time. After the first successful load, the Template insertion is coming up empty. that is, isntead of the full template being inserted, i'm just getting:
<!-- ngInclude: 'focus.html' -->
And not the actual template located in that file. Does anybody have any Idea what is going on here?
I apologize in advance for the relatively complex directive, if anybody has any suggestions for refactoring it, I am an open book.
I think the problem I described is in async manner of getting the template from the server side. In case of cached content it didn't work. You used element bind to click which is anti-angular way and non-angular context (thus you needed yo call $apply). And in this case I guess the problem that $scope.apply works before the content of the compiled node itself is processed (because you get the template immediately from the cache). If you call $scope.apply from the $timeout function or (better) change the function to scope function linked with templates via ng-click it works as expected.
I think for the goal are are going to achieve you are taken a bit wrong design which looks a bit weird. Anyway I can show you the problem - you are using separate template which is compiled inside of the ng-include. ng-include directive actually performs $http request with using template cache (default behavior) because of this the data is loaded only once and the template isn't inserted. If you add random seed to the template URL or make $templateCache.remove('focus.html') before compiling that can solve your issue (but I don't think it's good solution as it makes http call each time). You should definitely re-factor your code to make it more clean.
I changed
controller.former = angular.element('<div ng-include="\'focus.html\'"></div>');
to:
controller.former = angular.element('<div><div ng-include="\'focus.html\'"></div></div>');
By wrapping the template into a parent container, I ensure that controller.former is always a reference to a container that holds all of the elements generated during compile time. without this fix, sometimes controller.former would only be selecting the comment node that precedes the inserted material. This resolves causes problems when i'm passing that selector into $animate.enter or $animate.leave, because it ends up only trying to animate that single comment node and ignoring it's next sibling.

AngularJS jquery.flot chart directive DOM collision

i'm working with angular js now for about ke 4 months and despite all the "first step failures" like not emphasising the async way anuglar thinks, I'm facing a problem I don't really understand. It's not that easy to describe.
I have a provider which registrates directives within the routeprovider's resolve function - during config phase. To compile programmatically preconfigured directives I create them on the specific controller call of each route. Acutally the directive I'm adressing here is a complex flotchart directive. It retrieves data from a rest api, transformes the retrieved data and prepares different kinds of option setups like proper stacked line charts or simple piecharts. Every single step takes its time, so I introduced promises to be sure that everthing is at it's right place before I finally call something like "$.plot".
So now I have the following situation: Imagine a singlepage app with two tabs. Each tab - like a first class menu item - refers to a new page with a new controller to process and new partials to render. For each page i have beside other directives one of these heavy flotchart directives to render. actually it takes about 5 seconds to render the chart. So we assume that we really start the app from beginning - like pressing F5. Now I enter the first page the first time and within the mentioned 5 seconds I switch tabs to enter the next page. I get to the next page, see different partials, layouts and stuff and a loading chart - but actually the directive of the first page is still bound to its link phase of that heavy flotchart directive (still preparing options for flot and calculating data to output graphically).
My problem is that this link phase actually really ends within a completely different template/route/controller context and gets stuck. It crashes with a console "replace" error from jquery.flot. I think this error means that flot tries to plot into a div which does not exist anymore. But that error occures just when I switch tabs during the link phase of the first page's heavy flot directive. It doesn't happen when the first page's chart is fully rendered and doesn't happen when the first page's directive hasn't entered its link phase (or am i missing something??). I tried placing some console.logs directly BEFORE hitting the jquery "$.plot" - remember only of the first page chart directive to dive into what's acutally happening. And the strange thing is when I manage to switch tabs within these magic 5 seconds, I still get the console log entries from the first page entry although I'm on a different page. And now guess what. That's strange - acutally two directive link phases are running side by side and one of them on a completely different view (or isn't it completely different, because its a singel page app?). Imagine I plot ("render") the chart in exactly the same div id - like $('#flot-chart'). so I have html parts containing id="flot-chart" on the first page AND on the second. when I now switch from the first to the second page (not finishing the first chart) I get the chart from the first page rendered in the #flot-chart div of the second page and like half a second later the actually correct chart rendered in that same div. So actually the link phase of the first page's chart directive ends in a completely different page in a way showing 2 charts consecutively. I know jquery.flot depends on DOM manipulation via jquery and that might be the problem (perhaps THAT'S the only real explanation for my problem), because jquery DOM manipulation is out from the angular way of life.
Or are there other explanations? I acutally solved the problem via $routeChangeStart listening and killing the $.plot process, but are there some hints, suggestions, explanations for that behaviour?
Plunker flot chart directive DOM collision
I have prepared a plunker which shows kind of a similar behaviour. i've delayed the creation of the directive and the directive's async data and option retrieval methods to somehow mock the behaviour of my app. this is non production code but describes simplified the way my problems occure. when you "fast click" the menu item one after the other many times, you can sometimes force angular to show 2 charts in one page. acutally one directive is linking and doing stuff in a different partial ? i know i'm missing something in my mind ... please give me a hint.
i used chrome for reproducing the error. stop the the plunker and press 'run'. directly after pressing 'run' click as fast as you can both links a couple of times.
Thanks a lot!

Resources