AngularJS Navigation does not work after tinymce directive - javascript

I have problem I can't figure out but I do have a hint. Before integrating TinyMCE the main navigation was working fine eg links Settings, Analytics, Setup; it isn't working now if you click them.
Here is my js file:
var app_htmleditor_module = angular.module('app_htmleditor', ['components']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/', {templateUrl: getBaseURL()+'public/tpl/app/htmleditor.htm', controller: HtmlEditorCtrl, reloadOnSearch:false }).
otherwise( {redirectTo: '/'});
}
]);
angular.module('components', []).directive('imageUpload', function () {
return {
restrict: 'E',
scope: {
uploaderid:'#uploaderid'
},
templateUrl: '/public/tpl/imageupload.htm'
}
});
app_htmleditor_module.directive('uiTinymce', function() {
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
element.tinymce({
// Location of TinyMCE script
script_url: 'http://resources.holycrap.ws/jscripts/tiny_mce/tiny_mce.js',
// General options
theme: "simple",
// Change from local directive scope -> "parent" scope
// Update Textarea and Trigger change event
// you can also use handle_event_callback which fires more often
onchange_callback: function(e) {
if (this.isDirty()) {
this.save();
// tinymce inserts the value back to the textarea element, so we get the val from element (work's only for textareas)
//ngModel.$setViewValue(e.getBody().innerHTML);
ngModel.$setViewValue(element.val());
scope.$apply();
return true;
}
}
});
}
}
});
And I added above tinymce directive into textarea using ui:tinymce like this:
<textarea ui:tinymce ng-model="data.html_tab" id="{{fileUploaderID}}_html_tab" name="{{fileUploaderID}}_html_tab" style="width:600px; height:300px"></textarea>
Notice ui:tinymce above. If I remove that, the navigation works fine again. So how do I make my navigation work with ui:tinymce added in textarea?
DEMO URL:
http://dev-socialapps.rkm-group.com/app/htmleditor/index#/
Any help will be greatly appreciated. Thanks
Update:
As suggested, I added ui js file to my template file first:
<script src="https://raw.github.com/angular-ui/angular-ui/master/build/angular-ui.js"></script>
Then In my js file, I added:
var app_htmleditor_module = angular.module('app_htmleditor', ['components', 'ui']).
config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/', {
templateUrl: getBaseURL()+'public/tpl/app/htmleditor.htm',
controller: HtmlEditorCtrl,
reloadOnSearch:false
}).
otherwise( {redirectTo: '/'});
}
]);
app_htmleditor_module.value('ui.config', {
tinymce: {
theme: 'simple'
}
});
And in textarea tag:
<textarea ui-tinymce ng-model="tinymce" id="{{fileUploaderID}}_html_tab" name="{{fileUploaderID}}_html_tab" style="width:600px; height:300px"></textarea>
But I am getting error:
ReferenceError: tinymce is not defined
Though ui js file is added fine, I confirmed by viewing source code and clicking on link

Have you tried the latest version of the tinymce directive in the angular-ui library?
Demo
JS file

Related

Angular. how to compile directive inside directive?

I have
<div id="content"><div>
I want to insert my directive. I did
html = $compile('<test></test>')($scope);
$("#content").html(html);
My directive:
app.directive("test", function ($compile, $route) {
return {
restrict: "E",
templateUrl: "/Templates/test.html",
controller: function ($scope, $location) {},
controllerAs: "page"
};
});
"/Templates/test.html":
... some code ...
<category></category>
directives test and category upload some data from server.
For some reasons category works, but test doesn't.
Anybody knows why?
Thanks
You could be required to recompile your directive. Add following code at the end of link function:
$compile(element.contents())(scope);
Some useful info here: $complie

Bootstrap and Angular JS button issue

I have this bootstrap and Angular JS app. I am using the following directive to show active navigation links:
mainControl.directive("myDataToggle", function(){
function link(scope, element, attrs) {
var e = angular.element(element);
e.on('click', function(){
e.parent().parent().children().removeClass('active');
e.parent().addClass("active");
})
}
return {
restrict: 'A',
link: link
};
});
Problem is this works fine in the nav, but if I have a button link that links to the separate sections of the app, the main nav at the top does not get updated To reflect which view I am in?
Any ideas?
The problem is that you're setting the class when you're clicking the link, not when you are navigating.
I presume you're using the ngRoute. If so you can try this approach:
Provide a name for your routes
$routeProvider.
when('/', {
templateUrl: 'views/home.html',
name: 'home'
}).
when('/about', {
templateUrl: 'views/about.html',
name: 'about'
});
Than add $route to your main controller, and pass it on to $scope
function MainCtrl($scope, $route) {
$scope.$route = $route;
}
Now you can add the active class using ng-class
<a ng-class="{active: $route.current.name == 'home'}"> Home </a>
<a ng-class="{active: $route.current.name == 'about'}"> About </a>
demo: https://jsfiddle.net/jkrielaars/mao8kx0L/2/

Apply Angular Controller to a Template

So, I'm not sure what it is I'm asking, but I want to achieve this:
Index.html:
<div ng-view>
</div>
<script>
angular.module('myApp', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', { controller: "HomeController", templateUrl: '/Partials/Home/Dashboard.html' });
$routeProvider.otherwise({ redirectTo: '/' });
}]);
</script>
Home/Dashboard.html:
<h2 class="page-header">{{welcome}}</h2>
<!-- Insert my reusable component here -->
My reusable component would reside in MyComponent/Component.html and have the controller myApp.component.controller associated with it.
So effectively I want to drop in the resuable component into the page and bind it to my controller. So I got as far as having this:
.directive('MyComponent', function() {
return {
restrict: 'E',
scope: {
},
templateUrl: '/MyComponent/Component.html'
};
});
So how do I now bind my controller to it? Do I do this:
.directive('MyComponent', function() {
return {
restrict: 'E',
resolve: function () {
return /* resolve myApp.component.controller */;
},
templateUrl: '/MyComponent/Component.html'
};
});
When a directive requires a controller, it receives that controller as the fourth argument of its
link function.
.directive('MyComponent', function() {
return {
restrict: 'E',
controller: 'MyController', // attach it.
require: ['MyController','^ngModel'], // required in link function
templateUrl: '/MyComponent/Component.html',
link: function(scope, element, attrs, controllers) {
var MyController = controllers[0];
var ngModelCtlr = controllers[1];
///...
}
};
});
The ^ prefix means that this directive searches for the controller on its parents (without the ^ prefix, the directive would look for the controller on just its own element).
Best Practice: use controller when you want to expose an API to other directives. Otherwise use link.
You can assign controllers to directives:
.directive('MyComponent', function() {
return {
restrict: 'E',
controller : 'HomeController',
templateUrl: '/MyComponent/Component.html'
};
});
So I just want to clarify a few things up here.
/MyComponent/Component.html:
<h2>{{welcome}}</h2>
/mycomponent.directive.js:
.directive('MyComponent', function() {
return {
restrict: 'E',
controller : 'ComponentController',
templateUrl: '/MyComponent/Component.html'
};
});
the above bound like this in index.html:
<h2>{{welcome}}</h2> <!-- this is from ng-controller = HomeController -->
<my-component></my-component> <!-- this is scoping from ng-controller = ComponentController -->
This generates the result
<h2>Hello from MyComponent</h2>
<h2>Hello from MyComponent</h2>
It appears that the ComponentController has taken over the entire scope. I then changed the directive to this:
.directive('MyComponent', function() {
return {
restrict: 'E',
// controller : 'ComponentController',
templateUrl: '/MyComponent/Component.html'
};
});
And changed the index.html to this:
<h2>{{welcome}}</h2> <!-- this is from ng-controller = HomeController -->
<div ng-controller="ComponentController">
<my-component></my-component> <!-- this is scoping from ng-controller = ComponentController -->
</div>
This gave the correct output:
<h2>Welcome from HomeController</h2>
<h2>Welcome from ComponentController</h2>
Then I changed the directive again to this:
.directive('MyComponent', function() {
return {
restrict: 'A', // <----- note this small change, restrict to attributes
// controller : 'ComponentController',
templateUrl: '/MyComponent/Component.html'
};
});
I changed index.html to this:
<h2>{{welcome}}</h2>
<div ng-controller="ComponentController" my-component></div>
And this also produced the desired output, just in less lines of code.
So I just hope this clarifies directives to people a bit better. I put this on for completeness and the steps that I took to achieve this. Obviously I had some help from the other answers which pointed me in the right direction.

Angular and youtube iframe issue

I'm trying to add a youtube video to my app, but angular removes the iframe code and does not appear, I'm using this
<div class="content-read" ng-bind-html="data.content"> </ div>
try using ng-bind-html-unsafe, but I think this was removed from the current version of angularjs
I'm using angular 1.2.3
I have also this
app.config(['$sceDelegateProvider', function($sceDelegateProvider) {
$sceDelegateProvider.resourceUrlWhitelist([
'self',
'http://www.youtube.com/**',
]);
}]);
Any ideas?
thanks
the best solution I found, is to create a directive that meets the function of ng-bind-html-unsafe
app.directive('ngBindHtmlUnsafe', ['$sce', function($sce){
return {
scope: {
ngBindHtmlUnsafe: '=',
},
template: "<div ng-bind-html='trustedHtml'></div>",
link: function($scope, iElm, iAttrs, controller) {
$scope.updateView = function() {
$scope.trustedHtml = $sce.trustAsHtml($scope.ngBindHtmlUnsafe);
}
$scope.$watch('ngBindHtmlUnsafe', function(newVal, oldVal) {
$scope.updateView(newVal);
});
}
};
}]);

How to require a controller in an angularjs directive

Can anyone tell me how to include a controller from one directive in another angularJS directive.
for example I have the following code
var app = angular.module('shop', []).
config(['$routeProvider', function ($routeProvider) {
$routeProvider.when('/', {
templateUrl: '/js/partials/home.html'
})
.when('/products', {
controller: 'ProductsController',
templateUrl: '/js/partials/products.html'
})
.when('/products/:productId', {
controller: 'ProductController',
templateUrl: '/js/partials/product.html'
});
}]);
app.directive('mainCtrl', function () {
return {
controller: function ($scope) {}
};
});
app.directive('addProduct', function () {
return {
restrict: 'C',
require: '^mainCtrl',
link: function (scope, lElement, attrs, mainCtrl) {
//console.log(cartController);
}
};
});
By all account I should be able to access the controller in the addProduct directive but I am not. Is there a better way of doing this?
I got lucky and answered this in a comment to the question, but I'm posting a full answer for the sake of completeness and so we can mark this question as "Answered".
It depends on what you want to accomplish by sharing a controller; you can either share the same controller (though have different instances), or you can share the same controller instance.
Share a Controller
Two directives can use the same controller by passing the same method to two directives, like so:
app.controller( 'MyCtrl', function ( $scope ) {
// do stuff...
});
app.directive( 'directiveOne', function () {
return {
controller: 'MyCtrl'
};
});
app.directive( 'directiveTwo', function () {
return {
controller: 'MyCtrl'
};
});
Each directive will get its own instance of the controller, but this allows you to share the logic between as many components as you want.
Require a Controller
If you want to share the same instance of a controller, then you use require.
require ensures the presence of another directive and then includes its controller as a parameter to the link function. So if you have two directives on one element, your directive can require the presence of the other directive and gain access to its controller methods. A common use case for this is to require ngModel.
^require, with the addition of the caret, checks elements above directive in addition to the current element to try to find the other directive. This allows you to create complex components where "sub-components" can communicate with the parent component through its controller to great effect. Examples could include tabs, where each pane can communicate with the overall tabs to handle switching; an accordion set could ensure only one is open at a time; etc.
In either event, you have to use the two directives together for this to work. require is a way of communicating between components.
Check out the Guide page of directives for more info: http://docs.angularjs.org/guide/directive
There is a good stackoverflow answer here by Mark Rajcok:
AngularJS directive controllers requiring parent directive controllers?
with a link to this very clear jsFiddle: http://jsfiddle.net/mrajcok/StXFK/
<div ng-controller="MyCtrl">
<div screen>
<div component>
<div widget>
<button ng-click="widgetIt()">Woo Hoo</button>
</div>
</div>
</div>
</div>
JavaScript
var myApp = angular.module('myApp',[])
.directive('screen', function() {
return {
scope: true,
controller: function() {
this.doSomethingScreeny = function() {
alert("screeny!");
}
}
}
})
.directive('component', function() {
return {
scope: true,
require: '^screen',
controller: function($scope) {
this.componentFunction = function() {
$scope.screenCtrl.doSomethingScreeny();
}
},
link: function(scope, element, attrs, screenCtrl) {
scope.screenCtrl = screenCtrl
}
}
})
.directive('widget', function() {
return {
scope: true,
require: "^component",
link: function(scope, element, attrs, componentCtrl) {
scope.widgetIt = function() {
componentCtrl.componentFunction();
};
}
}
})
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
$scope.name = 'Superhero';
}

Categories