I have the following directive in a typescript file:
ProjectDirectivs.ts
/// <reference path="../module.ts"/>
module BalancingApp.App.Directives {
angular.module('balancingApp')
.directive('wbProject', function() {
return {
template: "<p>Projectdetails</p>"
};
})
;
}
When I call it inside of a template for a project detail page
ProjectDetailPage.html
<ion-view view-title="Projekt Details">
<ion-content class="padding">
<h1>Projekt Details</h1>
<div wbProject>
</div>
</ion-content>
</ion-view>
it has no effects, there seems just to be empty space below the heading.
Do I do something wrong? How can I test if the wbProject directive actually is used?
If I edit the typescript file and insert errors, the whole page keeps in loading stage, so it seems that the file gets actually used and is not ignored.
Angular converts the directive name into camel-case in template, so you should use wb-project instead of wbProject in template
Try this
angular.module('balancingApp')
.directive('wbProject', function() {
return {
restrict: 'AE',
template: "<p>Projectdetails</p>"
};
});
Related
I have a view with the controller name "Listctrl" in this view i want to have a different controller named "LocationCtrl". At the moment i do this like this:
Routing
.state('list', {
url: '/list',
templateUrl: 'templates/list.html',
controller: "ListCtrl",
cache: false
})
HTML (list.html)
<ion-view ng-init="ini()" ng-controller="LocationCtrl">
<ion-header-bar class="banner-top ext-box" align-title-h="left">
<div class="int-box2"><h2 id="s_back1">STORIE</h2></div>
</ion-header-bar>
<ion-content class="has-header has-footer no-bgColor start" overflow-scroll="false" has-bouncing="false">
<div class="container-list">
How should i solve this correctly? I need two controllers for the same view, but on different places, because i want to reuse the controller code in different views.
At the moment <ion-view ng-init="ini()" ng-controller="LocationCtrl">
does not run the LocationCtrl
Any help much appreciated!
There is no possibility to have two controllers for one view, as this doesn't make sense. If you have a functionality that should be shared, use controller inheritance, but this is possible only if LocationCtrl adds its methods to $scope:
var app = angular.module('angularjs', []);
app.controller('LocationCtrl', function($scope) {
// I have functionality to share
});
app.controller('ListCtrl', function($scope, $controller) {
$controller('LocationCtrl', {$scope: $scope}); // This adds properties to ListCtrl's scope
});
Another approach could be to put ng-controller="LocationCtrl" to a wrapper div:
<ion-view ng-init="ini()">
<div ng-controller="LocationCtrl">
<ion-header-bar class="banner-top ext-box" align-title-h="left">
<div class="int-box2"><h2 id="s_back1">STORIE</h2></div>
</ion-header-bar>
But this doesn't seem like a good option. A better approach would be to create a component/directive with the functionality defined on LocationCtrl and use it somewhere in your view:
<ion-view ng-init="ini()">
<component-with-location-ctrl-functionality></component-with-location-ctrl-functionality>
If you are setting controller "ListCtrl" for the route, and you want to create place inside this route with another controller you can create directive with isolated scope
app.directive('yourNewDrctv', function() {
return {
restrict: 'E',
templateUrl: 'yourNewTmpl.html',
scope: {},
controller: 'yourNewCtrl'
};
});
and use it in your template "templates/list.html" anywhere
just like that:
<your-new-drctv></your-new-drctv>
I am trying to use the angular-seed project (https://github.com/angular/angular-seed) to start a new project. I am trying to add in a new directive.
Created testDirective.js file :
'use strict';
angular.module("myApp.testDirective", [])
.directive("testDirective",
function() {
return {
template : "<h1>Made by a directive!</h1>"
};
});
Included the file in index.html, added "myApp.testDirective" into app.js, in view1.js I added :
'use strict';
angular.module('myApp.view1', ['ngRoute','myApp.testDirective'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/view1', {
templateUrl: 'view1/view1.html',
controller: 'View1Ctrl'
});
}])
.controller('View1Ctrl', [function() {
}]);
and view1.html looks like :
<p>This is the partial for view 1.</p>
<div testDirective></div>
However, when I run the app, nothing shows up where testDirective is. Not sure where I've gone wrong.
Whenever you wanted to use directive on the html, you should just replace capital letter to small case prefix - with it. Directive normalization process convert that test-directive to testDirective while compiling directive.
<div test-directive></div>
When including attribute directives inside the opening tag of an HTML element, they must be converted to dashes.
<div test-directive>
I have a little widget I'd like to use over and over on a single page. It has its own controller. Problem is it needs a piece of data to operate (basically a key), and each key is contained in the parent controller.
Here is an example (which is obviously wrong)
http://plnkr.co/edit/VajgOr1LqpLDnbEJcvor?p=preview
script:
angular.module('myApp', [])
.controller('ParentCtrl', ['$scope',
function($scope) {
$scope.keyForChartABC = "somekey1";
$scope.keyForChartXYZ = "somekey2";
$scope.keyForChartLALA = "somekey3";
}
])
.controller('ChartCtrl', ['$scope',
function($scope) {
//todo: have $scope.key assigned from parent somehow
//not shown: use $scope.key to pull data and format chart data
}
])
index:
<!-- ng-init like this is quite wrong -->
<div ng-init="key = keyForChartABC"
ng-include="'chartwidget.html'"></div>
<hr>
<div ng-init="key = keyForChartXYZ"
ng-include="'chartwidget.html'"></div>
<hr>
<div ng-init="key = keyForChartLALA"
ng-include="'chartwidget.html'"></div>
chartwidget:
<div ng-controller="ChartCtrl">
<p>Drawing chart for data: {{key}}</p>
<p>some chart directive here</p>
</div>
As you can see in the plunker, what I tried here with ng-init doesn't work - key for all the sub-controllers end up with the same value.
I've gotten this to work with ng-repeat and an array of data in the parent, somehow $index gets set in each child to the right index and stays that one value. But I'd like to avoid using ng-repeat in this case so I can have more control of the layout.
Creating re-usable widgets is exactly the purpose of Directives. You can create a directive which handles the output of your widget quite easily.
I forked your plunker and modified it to change it to use a directive.
Here are a few highlights:
First, your template no longer needs the controller defined within it.
<div>
<p>Drawing chart for data: {{key}}</p>
<p>some chart directive here</p>
</div>
Next, the directive is defined, with an isolate scope which is unique to each instance of the directive:
.directive('chartWidget', function(){
return {
restrict: 'E',
scope: {
key: '='
},
templateUrl : 'chartwidget.html'
}
})
Lastly, the directive is declared in the HTML. Note the camel-case name of the directive in the JavaScript, but the hyphenated name in the HTML:
<div>
<chart-widget key="keyForChartABC"></chart-widget>
<hr>
<chart-widget key="keyForChartXYZ"></chart-widget>
<hr>
<chart-widget key="keyForChartLALA"></chart-widget>
</div>
Edit
I updated the plunker to show binding the directive property to an inner controller. This method uses the ControllerAs syntax to define the controller, and binds the directive's scope to the controller scope.
Relevant changes:
.directive('chartWidget', function(){
return {
restrict: 'E',
scope: {
key: '='
},
templateUrl : 'chartwidget.html',
controller: 'chartWidgetController',
controllerAs: 'ctrl',
bindToController: true
}
})
.controller('chartWidgetController', function(){
console.log(this.key);
})
And a small change to the template to support ControllerAs:
<div>
<p>Drawing chart for data: {{ctrl.key}}</p>
<p>some chart directive here</p>
</div>
Note that trying to use ng-controller= in the template will cause the template to have a different scope object from the scope object created for the directive, and the controller would not have access to the properties defined on the directive.
Also note, bindToController is a feature of angular 1.3.x or higher. in angular 1.2.x or earlier, your only option was to use $scope.$watch to monitor the isolate scope for changes.
Let's say i have a <lightbox> directive in AngularJS. The lighbox has two params: title and image_source, which in turn are referenced in its HTML with {{title}} and {{image_source}}.
Because I use Bootstrap's modal, the directive must say on the outmost scope of the page (if I insert it in the inner DOM elements it can have display problems).
I understand that if the directive is in a "parent" controller, there are many ways to interact:
<div ng-controller="ParentCtrl">
<lightbox src='mySrc' ... >
</div>
but I am forced to pull it out:
<div ng-controller="ParentCtrl">
</div>
<lightbox ...>
(Edit: to clarify: i am forced to put the modal OUT of the controller (which is a template called by a route) because it interacts badly if it is not. Another way would be to wrap all the page in a Main controller, but I'm not sure it's elegant.)
But how do I access the internal directive scope and change dynamically the two values?
(Edit: thought of using a service, not sure if it is the right way, though)
this is method to call rootscope to directive
angular.module("directiveAPP", [])
.controller("directiveController", function ($scope, $rootScope) {
$rootScope.src = "http://picbook.in/wp-content/uploads/2014/07/image_123.jpg";
$rootScope.title = "hai";
}).directive("lightBox", function () {
return {
restrict: 'E',
template: '<div><img src="{{imageSrc}}" title="{{imageTitle}}" width="100px" style="border:solid #ddd 1px;" /></div>',
scope: {
imageSrc: '=',
imageTitle: '='
}
};
});
this one use of directive
<div ng-app="directiveAPP">
<div ng-controller="directiveController">
<light-box image-src="src" image-title="title"></light-box>
</div>
<light-box image-src="src" image-title="title"></light-box>
</div>
FIDDLE LINK
Using the AngularJS,
I want to use ng-include to make my code generic.
So here is my problem:
I want to have my 'ang-attribute.html' file used in the ng-include to be as generic as possible, and for that I want to get the attribute name outside of the html.
With something like this:
<div data-field-name="display_name">
<div ng-include="'ang-attribute.html'"></div>
</div>
In my html file I would like to use the data-field-name, and then use it again with a different value.
I tried to get it via DOM... and couldn't find a way to do that.
So in my ng-include html file I have the following line:
<div ng-controller="attributeCtrl">
<div class="my-profile-constant-text">{{displayAttribute}}:</div>
....
</div>
Maybe there is a way to pass a constructor to the controller and then I could pass my data-field-name into it?
Or any other solution?
Thanks!
I believe you want to be looking at directives, this has an attributes object easily accessible after the dom has rendered to re-use.
Html
<my-directive field-name="display_name"></my-directive>
Directive
angular
.module("myApp", [])
.directive("myDirective", function() {
return {
restrict: "E",
template: "<div>{{exposeAttribute}}</div>",
//templateUrl: "mytemplate.html",
link: function(scope, element, attr) {
scope.exposeAttribute = attr.fieldName;
}
};
});
http://jsfiddle.net/mhCaD/