:) I have a input in the body of my index.html file Which acts like a static header to my templates. The only problem is that i have the filter in my template like so:
<!-- Home Template -->
<script id="home.html" type="text/ng-template">
<ion-view title="plz help">
<ion-content>
<div class="list" id="list" ng-repeat="phone in phones | filter:query">
...
</div>
</ion-content>
</ion-view>
</script>
So that makes it "2 separate files" (they are both inside index.html). This makes it so that i can't for example "clear the filter" from a button in my header that's outside of the template.
Is there any way I can "include" the different "files" in each other so that i can execute JavaScript in in both "files"?
Thanks in advance!
You can do this with a nested scope. Because query live in root scope, is visible from scope of your controller. You have exemple here
But, sometimes there is a problem that variable from root or parent scope is not visible in nested scope if previously is not defined in main controller. Also, you can use $rootScope service to easier access.
Hope to I clarified a little.
Related
I have some content I wish to load into a div using Angular. For example:
<div class="number-and-description" ng-controller="thingDetails">
<div class="number" ng-click="loadContent(thing.number, thing.description, thing.status)" ng-cloak>{{ thing.number }}</div>
<p class="description" ng-click="loadContent(thing.number, thing.description, thing.status)" ng-cloak>{{ thing.description }}</p>
</div>
I have another view outside of this div like this:
<!-- Main Content Area -->
<section class="main-content group" ng-controller="thingDetails">
<h1 ng-cloak>{{ thingNumber }}</h1>
<div ng-cloak>{{ thingDescription }}</div>
<div ng-cloak>{{ thingStatus }}</div>
</section>
In my app.js file, I have this code:
thingApp.controller('thingDetails', ["$scope", function($scope) {
$scope.loadContent = function(number, description, status) {
$scope.thingNumber = number;
$scope.thingDescription = description;
$scope.thingStatus = status;
return $scope;
};
}]);
My question is, why doesn't the main content area div update when these values are changed? Right now it remains blank. thing.number, thing.description loads fine in the div I am clicking on - this data is coming from hardcoded JSON which appears fine. The issue is that when I click on the div, the OTHER main content div doesn't show/update the data. Could someone please help me out? Note that when I console.log(number) or console.log(description) etc. I can see the correct values, so they are being passed correctly to the loadContent() function.
You have two separate instances of controller thingDetails , not one. They each have their own scope and do not share anything directly. A simple way to see this is put a console.log() in your controller and you will see it run each time the controller initializes
For controllers to share data you use a service and inject that service wherever it needs to be accessed.
Alternatively perhaps you don't need two instances and can wrap them in one scope in your view
You are basically creating two controllers here with two different scopes. Thus, in the outer div, $scope.thingNumber, description, etc. are undefined as you are only changing the values on the inner scope.
A quick but messy fix to this problem would be to change your $scope's to $rootScopes. The proper way to do this though is via services/factories.
Here is a Plunker: http://plnkr.co/edit/F6QM4KUU8DPNq6muInGS?p=preview
Including an html file with ng-include, having set the ng-controller in the same tag, doesn't update the controller's scope models. Using the ng-model directly inside of the html works perfectly fine, and also setting the controller inside of the included html file is working. But ng-include together with ng-controller $scope.models don't update and stay as they are.
For whatever reason if you set the model inside of the controller, it is done suring it's loading. But having a method setting the model (not included in the plunker) only changes the mdoel inside of the controller's scope and not the html one.
Also if I use an ng-include in the scope of another controller and want to access the included models return undefined or the value you set the model to. Calling methods from the included html works fine in both cases, but they can't really operate as the values are wrong.
I saw that a similar issue has already been postet and should have been resolved (https://github.com/angular/angular.js/issues/4431), but as you can see in the plunker for me it doesn't.
Do I miss something, or is this a problem of angular?
Kind Regards,
BH16
PS: Here is the code from the Plunker:
index.html - body
<body ng:controller="MainCtrl">
<input type="text" ng:model="input">{{input}} {{getInput()}}
<div ng:include="'main2.html'" ng:controller="Main2Ctrl"></div>
</body>
main2.html
<div>
<input type="text" ng:model="input2">{{input2}} {{getInput2()}}
</div>
script.js
angular.module('testApp', [])
.controller('Main2Ctrl', function($scope) {
$scope.input2 = 1234;
$scope.getInput2 = function() {
console.log("input2");
return $scope.input2;
};
})
.controller('MainCtrl', function($scope) {
$scope.input = 1234;
$scope.getInput = function() {
console.log("input");
return $scope.input;
}
});
For all of those who are are also having this issue: Just use the controllerAs syntax: http://toddmotto.com/digging-into-angulars-controller-as-syntax/
This solves all of the issues above and simplifies the code A LOT!
This is the basic idea of controllerAs (taken from the site above):
<div ng-controller="MainCtrl as main">
{{ main.title }}
<div ng-controller="AnotherCtrl as another">
Scope title: {{ another.title }}
Parent title: {{ main.title }}
<div ng-controller="YetAnotherCtrl as yet">
Scope title: {{ yet.title }}
Parent title: {{ another.title }}
Parent parent title: {{ main.title }}
</div>
</div>
</div>
It's related to that ng-include creates it's own scope.
To see what's actually happens you can try plugin(for google chrome, probably something similar exists for others browser's too): "AngularJS Batarang", it will include additional tab to dev tools.
And possible solution will be:
main2.html:
<div ng:controller="Main2Ctrl">
<input type="text" ng:model="input2"> {{input2}} {{getInput2()}}
</div>
http://plnkr.co/edit/daIehNjxWdam3NyH3ww4?p=preview
Due to the structure of an existing project I'm working on, I'm stuck with a template that looks like this:
<div ng-app="example">
<div ng-controller="MainCtrl" id="inner">
{{ inside }}
</div>
</div>
<div ng-controller="MainCtrl" id="outer">
{{ outside }}
</div>
#outer is supposed to be using the same controller as #inner, but as it's located outside of ngApp's scope, {{ outside }} will not be evaluated. Unfortunately I can't change the template structure, so I tried to compile #outer's content like this:
app.run(function($rootScope, $compile){
$rootScope.$apply($compile(document.getElementById('outer'))($rootScope));
});
This works, but the controller function will be executed twice, which is not desired. Is there a better way to achieve my goal?
Working example on Plunker
what you could do instead, is NOT define ng-app at all in the html, and instead bootstrap angular via javascript.
for example you can do angular.bootstrap(document, ['example']); where 'example' is the angular module for the app for example angular.module('example', [
'ngResource', 'ui.router', ....
]);
you probably defined that yourself already.
This way, you define the ng-app on the entire document scope.
That is normal, you're initializing twice the controller. You could simply create another div, wrapping all the divs you want and use alias. But this will still initialize twice, but each div will have different values, like, {{inside}} on first div will not have the same as the second one has.
<div ng-app="example">
<div>
<div ng-controller="MainCtrl as FirstCtrl" id="inner"> // alias FirstCtrl
{{ inside }}
</div>
</div>
<div ng-controller="MainCtrl as SecondCtrl" id="outer"> // alias SecondCtrl
{{ outside }}
</div>
</div>
But if you intend to use just once the same controller, as far as I'm concerned, you'll have to wrap all divs you want to use the same controller, in just one div, like:
<div ng-app="example" ng-controller="MainCtrl">
<div id="inner">
{{inside}}
</div>
<div id="outer">
{{outside}}
</div>
</div>
This will initialize just once.
Other way, could be attaching ng-app and ng-controller in your html/body tags.
From what I read, the most common cause of this problem is when the controller is included in the template and in the route provider. In my case, only the parent template containing this html is being included in the router, and has its own controller. The sub-templates are being included as a result of a menu selection
So, whenever the menu item is selected, the template gets loaded in, and everything in the controller executes twice. Can it be a product of the the ng-switch or ng-include?
<span ng-switch on="selection">
<div ng-switch-when="0">
<div ng-include="'partials/one.html'" ng-controller="oneController"></div>
</div>
<div ng-switch-when="1">
<div ng-include="'partials/two.html'" ng-controller="twoController"></div>
</div>
<div ng-switch-when="2">
<div ng-include="'partials/three.html'" ng-controller="threeController"></div>
</div>
</span>
Edit:
The included partials do not include the controller again. I've triple checked that these controllers are not mentioned anywhere other than this piece of code. The contents of the one/two/three partials look like this, and the controller still runs twice.
<div>Nothing to see here.</div>
I am making an educated guess here... but does your "'partials/one.html'" also have a ng-controller="oneController" in it? If so, you either need to remove the ng-controller declaration from your include div or from your partial.
I'm trying to dynamically include a template into my index.html. The general structure of index.html is:
<body>
<header ng-controller="Main">
<section>
<!-- global stuff -->
</section>
<section ng-include="moduleName + '/views/menubar.html'">
<!-- module-based stuff -->
</section>
</header>
<div id="view" ng-view></div>
</body>
Sample URL
example.com/<app_name>/index.html#/<module_name>[/method_name]
I can't figure out how to update $scope.moduleName when the route changes. My trouble is two-fold:
The header's controller is Main, not the controller associated with the view, so I can't? update $scope.moduleName from the view's controller (because Main and the view's controller are siblings).
In Main, I tried setting a $scope.$on('$routeChangeSuccess',…), but apparently it is not notified of route changes.
I've thought of setting up a $rootScope.$on listener (as described in SO#15355346) for the route change and broadcasting down to children, who then emit back up their route, which is broadcasted back down so it is available to Main. But that seems heinous.
And I would really prefer to keep the header outside of ng-view.
EDIT I noticed that $route.current.scope has an object named with module_name (possibly because the name of the controller associated with the route's module_name is the same). I'm wondering if I might be able to somehow use the name of that object…
It's hard to say what's wrong in your code without the full picture. Things you show look fine to me.
Please see this plunk I've created to display the ability to do it. Take note that you also can extend route objects with custom properties, like moduleName here:
$routeProvider.when('/page1', {
template: 'one',
controller: 'one',
moduleName: 'firstModule'
});