I'm trying to use the ui-tinymce directive inside of another directive:
angular.module("risevision.widget.common.font-setting", ["ui.tinymce"])
.directive("fontSetting", ["$templateCache", function ($templateCache) {
return {
restrict: "AE",
template: $templateCache.get("_angular/font-setting/font-setting.html"),
transclude: false,
link: function ($scope, element, attrs) {
$scope.tinymceOptions = {
menubar: false,
statusbar: false
};
}
};
}]);
And _angular/font-setting/font-setting.html:
<div class="row">
<div class="col-md-12">
<textarea ui-tinymce="tinymceOptions" ng-model="tinymceModel"></textarea>
</div>
</div>
The TinyMCE editor shows up, but it's ignoring the configuration options I've set in $scope.tinymceOptions. That is, the menu bar and status bar still show.
Any thoughts as to why it's not working?
Thx.
I know I'm late to the party but I'm going to answer you in case someone has the same issue and can't find the answer.
TinyMce needs to be loaded only when the tinymceOptions variable has data so you need to wrap it in an ng-if:
<div class="row">
<div class="col-md-12" ng-if="tinymceOptions">
<textarea ui-tinymce="$parent.tinymceOptions" ng-model="$parent.tinymceModel"></textarea>
</div>
</div>
You can avoid using $parent (elements inside ng-if have their own scope) using controller as inside the directive if you are using Angular >1.4:
app.directive('someDirective', function () {
return {
scope: {},
bindToController: {
someObject: '=',
...
},
controllerAs: 'ctrl',
controller: function () {
var ctrl = this;
ctrl.message = 'Object loaded.';
},
template: '<div ng-if="ctrl.someObject">{{ctrl.message}}</div>'
};
});
Related
I have a directive that controls a personalized multiselect. Sometimes from the main controller I'd like to clear all multiselects. I have the multiselect value filling a "filter" bidirectional variable, and I am able to remove content from there, but when doing that I also have to change some styles and other content. In other words: I have to call a method belonging to the directive from a button belonging to the controller. Is that even posible with this data structure?:
(By the way, I found other questions and examples but their directives didn't have their own scope.)
function MultiselectDirective($http, $sce) {
return {
restrict: 'E',
replace: true,
templateUrl: 'temp.html',
scope: {
filter: "=",
name: "#",
url: "#"
},
link: function(scope, element, attrs){
//do stuff
scope.function_i_need_to_call = function(){
//updates directtive template styles
}
}
}
}
The best solution and the angular way - use event.
Live example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleOneController', function($scope) {
$scope.raise = function(val){
$scope.$broadcast('raise.event',val);
};
})
.controller('ExampleTwoController', function($scope) {
$scope.raise = function(val){
$scope.$broadcast('raise.event',val);
};
})
.directive('simple', function() {
return {
restrict: 'A',
scope: {
},
link: function(scope) {
scope.$on('raise.event',function(event,val){
console.log('i`m from '+val);
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="ExampleApp">
<div ng-controller="ExampleOneController">
<h3>
ExampleOneController
</h3>
<form name="ExampleForm" id="ExampleForm">
<button ng-click="raise(1)" simple>
Raise 1
</button>
</form>
</div>
<div ng-controller="ExampleTwoController">
<h3>
ExampleTwoController
</h3>
<form name="ExampleForm" id="ExampleForm">
<button ng-click="raise(2)" simple>
Raise 2
</button>
</form>
</div>
</body>
I think better solution to link from controller to directives is this one:
// in directive
return {
scope: {
controller: "=",
},
controller: function($scope){
$scope.mode = $scope.controller.mode;
$scope.controller.function_i_need_to_call = function(){}
$scope.controller.currentState = state;
}
}
// in controller
function testCtrl($scope){
// config directive
$scope.multiselectDirectiveController = {
mode: 'test',
};
// call directive methods
$scope.multiselectDirectiveController.function_i_need_to_call();
// get directive property
$scope.multiselectDirectiveController.currentState;
}
// in template
<Multiselect-directive controller="multiselectDirectiveController"></Multiselect-directive>
Lets start with some code
Html:
<rd-search-set type="'ActiveProfileContact'">
<form class="navbar-form navbar-static-top" role="search">
<rds-input />
</form>
</rd-search-set>
rds-input template:
<div class="input-group rd-search-wrap">
<div class="input-group-addon">
<i class="fa fa-search"></i>
</div>
<input type="text" value="" class="form-control" placeholder="{{'FIND_CONTACT' | translate | capitalize}}..." ng-modal="src.value" />
<div class="rd-search-state">
<i class="fa spin2D fa-spinner" ng-if="src.isBusy"></i>
<span class="text-muted rd-search-result" ng-if="!src.isBusy">{{src.amountString}}</span>
</div>
Javascript / AngularJs:
angular
.module("App")
.directive("rdSearchSet", rdSearchSet)
.directive("rdsInput", rdsInput);
function rdSearchSet() {
var directive = {
restrict: 'E',
scope: {
onSearch: "=onSearch",
searchForType: "=type",
relatedGuids: "=rdSearchRelatedGuids",
searchEventType: "=rdSearchEventType",
},
controller: "SearchController",
controllerAs: "src",
bindToController: true,
replace: false,
};
return directive;
}
rdsInput.$inject = ["rdBaseUrl"];
function rdsInput(rdBaseUrl) {
var directive = {
restrict: 'E',
replace: true,
templateUrl: rdBaseUrl + "Partials/Directives/Search/rdsInput.html",
require: "^rdSearchSet",
transclude: true,
scope: false,
};
return directive;
}
The problem
I'm having alot of trouble getting / setting data on the controller of the rdSearchSet directive. Last thing I tried is setting the rdsInput directive scope property to false, hoping that I can access the parent scope values using the controllerAs: "src" property of rdSearchSet.
My question in short: What is the best way to access the parent directive's controller(as) scope as transparent as possible? Like, use a Directive to load html and bind to parent directive scope properties, both ways.
EDIT:
I have moved the rdSearchSet directive html to a template that looks like this:
<form class="navbar-form navbar-static-top navbar-royal" role="search">
<rds-input />
</form>
<rds-list />
rdSearchSet.$inject = ["rdBaseUrl"];
function rdSearchSet(rdBaseUrl) {
var directive = {
restrict: 'E',
scope: {
onSearch: "=onSearch",
searchForType: "=type",
relatedGuids: "=rdSearchRelatedGuids",
searchEventType: "=rdSearchEventType",
},
templateUrl: rdBaseUrl + "Partials/Directives/Search/rdsSearchSet.html",
controller: "SearchController",
controllerAs: "src",
bindToController: true,
replace: false,
};
return directive;
}
The problem that still exists is that I am not able to use the ControllerAs prefix. The
text input field in rdsInput uses a ng-model="src.value" but the
value is not set in the rdSearchSet's Controller.
Two problems ... one is a simple typo for ng-model where you have ng-modal.
The other is isolated scope only works when you use a template, it doesn't work for existing html within the element.
If you move the <form> to a template your code will work
<rd-search-set></rd-search-set>
JS
function rdSearchSet() {
var directive = {
restrict: 'E',
templateUrl:'search.html',
scope: {
.....,
},
controller: "SearchController",
controllerAs: "src"
};
return directive;
}
DEMO
I m actually creating a directive that permit me to generate some graphs, with some parameters at this format :
<div anomalie-graph idsite="{{site._id}}" sector="true" controlleur="" anomalie=""
datedebut="dateDebutStats"
datefin="dateFinStats">
or
<div anomalie-graph idsite="{{site._id}}" sector="" controlleur="" anomalie="true"
datedebut="dateDebutStats"
datefin="dateFinStats">
This directive display correctly what I need.
The problem is that I want to reload the data inside this directive.
In fact, I use something like :
$scope.$on('reload', function () {
reload();
});
Inside of the directive controller.
Now that I have isolated my scope with
return {
restrict: 'EAC',
templateUrl: 'tpl/directive/TraitementAnomalieGraphDirective.html',
controller: controller,
scope: {
idsite: '#',
sector: '#',
controlleur: '#',
anomalie: '#',
datedebut: '#',
datefin: '#'
}
};
I cant listen to the scope event (because it's isolated), and I dont want to use $scope.$broadcast.
Before scope isolation, it worked great with the listener events. The problem was that I couldn't use this library multiple time in a view...
Can you help me ?
EDIT:
Here's my code :
Template:
<div class="row">
<div class="col-md-4">
<div anomalie-graph idsite="{{site._id}}" sector="true" controlleur="" anomalie=""
datedebut="dateDebutStats"
datefin="dateFinStats">
</div>
</div>
<div class="col-md-4">
<div anomalie-graph idsite="{{site._id}}" sector="" controlleur="true" anomalie=""
datedebut="dateDebutStats"
datefin="dateFinStats">
</div>
</div>
</div>
Here's the directive :
angular.module('app')
.directive('anomalieGraph', function () {
var controller = ['$scope', '$attrs', 'srv_traitementsVoirie', function ($scope, $attrs, srv_traitementsVoirie) {
var load = function () {
// code of reload
};
load();
$scope.$on('reload', function () {
load();
});
}];
return {
restrict: 'EAC',
templateUrl: 'tpl/directive/TraitementAnomalieGraphDirective.html',
controller: controller,
scope: {
idsite: '#',
sector: '#',
controlleur: '#',
anomalie: '#',
datedebut: '=',
datefin: '='
}
};
});
I'm trying to learn angular directives/transclusion to control the creation of some custom panels in my application. I'm going wrong somewhere with transcluded content which is not appearing in the html.
I have the following html markup:
<div panel-widget>
<!-- this transcluded content appears -->
<div panel-header></div>
<div panel-body>This content doesn't</div>
</div>
In my browser I can see the content after the panel-widget directive but not the content in the panel-body directive. Here are my directives, pretty simple so far...
// -----------------------------------------------------------
// PANEL WIDGET DIRECTIVE
// -----------------------------------------------------------
angular.module('myApp.panel')
.directive('panelWidget', [ function() {
return {
template: '<div class="panel panel-default"><span ng-transclude></span</div>',
restrict: 'A',
transclude: true,
};
}]);
//-----------------------------------------------------------
//PANEL WIDGET DIRECTIVE
//-----------------------------------------------------------
angular.module('myApp.panel')
.directive('panelHeader', [ function() {
return {
template: '<div class="panel-heading"><h3 class="panel-title"><em>This appears</em></h3></div>',
restrict: 'A',
scope: {
headerObj: '='
}
};
}]);
// -----------------------------------------------------------
// PANEL WIDGET DIRECTIVE
// -----------------------------------------------------------
angular.module('myApp.panel')
.directive('panelBody', [ function() {
return {
template: '<div class="panel-body"><span ng-translude></span></div>',
restrict: 'A',
transclude: true,
scope: {
panelBodyObj: '='
}
};
}]);
Does anyone know why the nested ng-transclude isn't working? Possibly an issue with the scope?
Thanks in advance!
You have a simple typo:
template: '<div class="panel-body"><span ng-translude></span></div>',
Replace ng-translude with ng-transclude.
http://plnkr.co/edit/iDiImVrhgP7ZJMa2YCz4?p=preview
:-)
You have misspelled ng-transclude in the panelBody directive :)
I have a directive, form where the rest of the html is given. The directive is given below
THis is the html for directive
<div test
input="{{guage.input}}"
>
</div>
angular.module('test', [])
.directive('test', function () {
"use strict";
return {
restrict: 'A',
scope: {
input: '='
},
templateUrl: 'gauge/gauge.tpl.html',
replace: true
});
The below is the html loaded after the directive compilation.
<div ng-controller="Testing">
<div>
<div id="{{guageid}}" class="gauge ng-isolate-scope" ng-model="gauge.input" data-service="/api/getDataResult/core-mon-status" guageid="fleet_online" description="Fraction of fleet online" unit="%" test="{{gauge.test}}" input="{{gauge.input}}" gauge="">
</div>
</div>
</div>
Now I have a parent controller above this dom element name is Testing.
From my controller if I change the {{guage.input}} its not displaying.
This is my controller
app.controller('Testing',['$scope','newdataLoad','$timeout',function($scope, newdataLoad, $timeout){
$scope.gauge = {};
$scope.gauge.input = 0;
});
What is the problem with my scope here.
As your scope defines the input with = you dont need the expression brackets.
<div test input="guage.input">
Using expression brackets will break the 2-way binding.
Optimization:
You can completely move you controller into the directive and still make use of the dependency injection
"use strict";
angular.module('test', []).directive('test', function () {
return {
restrict: 'A',
scope: {
input: '='
},
templateUrl: 'gauge/gauge.tpl.html',
replace: true,
controller: function($scope, newdataLoad, $timeout){
$scope.gauge = {};
$scope.gauge.input = 0;
}
}
});
The template code then :
<div>
<div id="{{guageid}}" class="gauge ng-isolate-scope" ng-model="gauge.input" data-service="/api/getDataResult/core-mon-status" guageid="fleet_online" description="Fraction of fleet online" unit="%" test="{{gauge.test}}" input="{{gauge.input}}" gauge="">
</div>
</div>
Remove curlies:
<div test input="guage.input">
</div>