AngularJS external javascript libraries do not run - javascript

First off I do apologize if this is already answered somewhere.
I am having an issue with AngularJS and external libs. For some reason when I attempt to have an external lib preform any sort of visual operation on an element it simply does not run.
One of such external libraries is the jscolor library which adds a really simplistic color picker (source link: http://jscolor.com)
Here is the include code in my index.html:
<link rel="stylesheet" type="text/css" href="app/css/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="app/css/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/interact.js/1.2.6/interact.min.js"></script>
<script src="app/js/lib/jscolor.min.js"></script>
<script src="app/js/lib/angular.min.js"></script>
<script src="app/js/lib/bootstrap.min.js"></script>
<script src="app/js/services/drawCanvas.js"></script>
<script src="app/js/services/colorpicker.js"></script>
<script src="app/js/app.module.js"></script>
<script src="app/js/components/drawableComponent.js"></script>
<script src="app/js/components/navigationComponent.js"></script>
<script src="app/js/components/canvasComponent.js"></script>
As you can see I do have jscolor.min.js included and I can assure you the file is there.
Here is the code in the relative component that contains the input that I am attempting to attach the JS color to.
(function(){
'use strict';
var app = angular.module('app');
app.component('drawable', {
templateUrl: 'app/js/components/drawableComponent.html',
controller: ['$rootScope','$scope', function ElementController($rootScope, $scope){
var self = this;
$scope.drawables = [];
self.$onInit = function() {
//$scope.drawables.push("test");
}
$scope.addDrawable = function(type, css) {
$scope.drawables.push({type:type,css:css});
console.log($scope.drawables);
}
$rootScope.$on("pushDrawable", function(event, args){
$scope.addDrawable(args.type,args.css);
});
self.animateTooltip = function(e) {
$(e.target).find(".draggableTooltip").toggle("slow").css("transform", "translateY(-60%)");
}
}
]
});
})();
Here is the template that is included in this controller (what angular calls when the component is included)
<div class="draggable" ng-repeat="drag in drawables track by $index" style="{{drag.css}}" ng-click="$ctrl.animateTooltip($event)">
<div class="draggableTooltip" style="display:none" >This is a tooltip <input class="jscolor" value="ab2567"></div>
<p> You can drag one element </p>
</div>
As you can see, I am attempting to include jscolor just like they explain in the examples on the jscolor documentation (honestly the implementation of this color picker should be simple and I have no doubts that I am doing it correctly, The calling and implementing that is)
What happens specifically is the input element is a simple text field much like what is shown on jscolor's site. However clicking that element and giving it focus does not launch the color picker as expected.
This is just one example of issues that I have had, another issue I have had and still do have is accordion nav menus dont animate slide down, or function at all whilst inside of a component's template. I think it has something to do with how angular injects templates, however I am wondering if someone can help me out with more experience as to show me the correct way of getting these external libraries to work.
Since the issue is a tad more complex I wasnt able to set up a jsfiddle.
Thanks for your help!

Why don't you try this:
https://ruhley.github.io/angular-color-picker/
It's fully integrated in angular without dependencies on jQuery.

Related

CSS file is not being loaded dynamically via ng-href

I am trying to dynamically load different css styles into my page using ng-href, but the page is not being updated with the activated style. Code is as follows:
<html ng-app="myapp" ng-controller="myController as myctrl">
<head>
<link rel="stylesheet" ng-href="../assets/css/{{ myctrl.style }}.css">
</head>
</html>
In my controller, I do the following:
vm.style = "redStyle";
pub.subscribe('style', function(theStyle) {
vm.style = theStyle;
});
The variable in the subscribe is updated with the new style once a publish has taken place. But the respective css file is not being loaded such that the style is updated on the page. Any ideas what I am missing out on?
Here is a working demo
It's very much the same as what you have so it's something else in your code. Hard to tell unless you put up all your code.
Assuming the stylesheet actually does exist, and the style variable is getting updated then my guess is that the culprit is
pub.subscribe()
If this callback is being triggered by something outside of angular then angular wont see the updated variable. You can bring it back into angular space like so:
pub.subscribe('style', function (theStyle) {
$scope.$apply(function(){
vm.style= theStyle;
});
});
Try this:
<link rel="stylesheet" data-ng-if="myctrl.style" data-ng-href="../assets/css/{{ myctrl.style }}.css" />
I solved it differently.
In my html, I gave the link element an id:
<link id="theme" rel="stylesheet" ng-href="../assets/css/{{theme}}.css">
And in the controller I say:
var myTheme = document.getElementById("theme");
var path = "../assets/css/{{theme}}.css";
myTheme.href = path.replace("{theme}", theme.class);

MMENU jquery plugin doubles all JS scripts

When I'm using mmenu jquery plugin, it doubles all js events and script call, except scripts in head section. What would be the possible solution for this? Any help would be greatly appreciated.
Sorry, but I can't show you full code, it's on working site. Mmenu starts that way in body section:
<script type="text/javascript">
$(document).ready(function() {
$("#my-menu").mmenu();
$("#my-menu").find( ".mm-subopen" ).addClass( "mm-fullsubopen" );
});
</script>
i tried mmenu in my production app and at first it gave me some headaches, but understanding how it works helped me to use it correctly.
Wrap your whole layout in a div without styles (so the website's style remains the same).
Place your menu markup outside your layout (inmediately bellow the body tag).
Add the the plugin at the end of your markup along with the initialization code.
Don't manipulate the inner content of the menu to do actions. Use it's API instead.
After you follow these tips, you should have a structure like this:
<html>
<head> ... </head>
<body>
<nav id="mymenu"> ... </nav>
<div> <!-- whole website in here --> </div>
<script src="js/mmenu.min.js"></script>
<script>
$(document).ready(function() {
var mmenu = $("#mymenu").mmenu();
// do not use code bellow, use the API instead.
// $("#my-menu").find( ".mm-subopen" ).addClass( "mm-fullsubopen" );
var api = mmenu.API(); // exposes methods to open() and close() the menu
});
</script>
</body>
</html>
Hope these setup works for you. It worked for me perfectly in my Meteor app.

AngularJS complains that initialization not defined for jquery

I am getting the below error when loading my page.
Error: initialize is not defined
#http://localhost:8082/js/vendor/jquery-1.11.2.js line 339 > eval:4:3
I want to replace the jqLite with the full version of jquery. I have read several stackoverflow questions on this subject and they imply that all that is required is to load jquery before angularjs. I have done this by simply moving the declaration for jquery above the angular.js. When I do this that is when the above error occurs. It does not give the error when I move the jquery below angularjs but then I cannot use such things as angular.element.
What am I doing wrong?
As far as loading the javascript for each library all I am doing is.
<script type='text/javascript' src="js/vendor/jquery-1.11.2.js"></script>
<script type='text/javascript' src="js/vendor/angular.js"></script>
as far as using jquery instead of lqlite, I am simply trying to use angular.element
var someElement = angular.element('#someelement');
I read a blurb to load jquery before DOMContentLoaded. I am not sure how to do this. I know how to write an event handler for DOMContentLoaded, but what do I do then.
Edited answer: I usually inject my JS script code in the header all inside of an IFFE. You'd also have to make sure you have the ng-app in there to specify the module. Finally I've made sure I actually include the dependent code in the header before my code.
See fiddle here
<head>
<script src="https://code.jquery.com/jquery-1.11.2.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js"></script>
<script>
(function() {
var testApp = angular.module("testApp", []);
function SomeController($scope) {
console.log('Started controller');
$scope.dirPanelElement = angular.element('#some-panel');
$scope.dirPanelElement.text('set test');
$scope.dirPanelElementText='got "'+$scope.dirPanelElement.text()+'" from panel'
}
testApp.controller("SomeController", SomeController);
})(); // IFFE
</script>
</head>
<body ng-app='testApp'>
<div id="content">
<div style="padding:50px">
<div data-ng-controller="SomeController">
<p align="center">Something</p>
<div id="some-panel"></div>
<div id="some-canvas">{{dirPanelElementText}}</div>
</div>
</div>
</div>
</body>

Gist-embed with Angular app

Trying to get gist-embed (https://github.com/blairvanderhoof/gist-embed) working within my Angular app but with no luck.
It works no problem on my homepage (which is not part of the Angular app) but when I use something like:
<code data-gist-id="<gist-id>"></code>
within the app it won't show. There are no messages in the console to explain why though.
Could someone explain why and offer a solution?
(function($) {
$(function() {
// find all elements containing "data-gist-id" attribute.
$('[data-gist-id]').each(function() {
var $elem = $(this),
id,
that lib is coded in such a way one cant really use it in angular,you'll have to look for a fork that offers a proper jquery plugin architecture you can use into a directive.That lib doesnt respect basic jQuery plugin architecture.
And no Error will show up because it's likely the .each will execute before your angular app runs.
As of June (version 1.8), the gist-embed project is now a jQuery plugin.
var $code = $('<code data-gist-id="474f6d7839fccffc4b2a"/>');
$code.appendTo('body').gist();
Basically you have to trigger "gist()" on the dom elements.
Try this, it worked for me very well.
// register trigger gist on every template include
$rootScope.$on('$includeContentLoaded', function() {
// initialize gist on new elements
angular.element(document).ready(function() {
if (typeof(angular.element(document).gist) === 'function') {
angular.element('[data-gist-id]').gist();
}
});
});
I put together a small library hoping to solve the problem.
Check it out : https://github.com/pasupulaphani/angular-gist-embed
Chekout this angular module : https://github.com/kiran3807/another-angular-gist-embed
This allows you to include the gists in your angular project in the form of a directive, one of the attributes for which is the gist-id :
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<script src="path/to/another-angular-gist-embed.js"></script>
<script>
angular.module('example',['another-angular-gist-embed']);
angular.module.controller('exampleCtrl',['$scope',function($scope){
$scope.gistId = 'a85770344febb8e30935';
}]);
</script>
</head>
</head>
<body ng-app="example">
<div ng-controller="exampleCtrl">
<!-- This loads a gist with a specific id-->
<gist-embed data-gist-id="gistId"></gist-embed>
</div>
</body>
</html>
Declaration : I am the author of this module

Javascript single page architecture with module autonomy

I just started this HTML5 project where we decided to make it a single page architecture by leveraging jQuery $.load() method. Unfortunately, as soon as the JS started to grow, we quickly started running into issues where the modules loaded into the master dashboard have no knowledge of their parent.
The architecture looks like this:
dashboard.html (master file)
moduleA.html
moduleA.js
moduleB.html
moduleB.js
moduleC.html
moduleC.js
Since we decided to also keep the JS as separate files, we are having to load all JS files through dashboard.html in order to invoke them individually when modulex is loaded.
So when loading moduleA.html into the dashboard we have to call its corresponding JS. To do this we simply wrote the JS using a Module Pattern so we can easily invoke it by doing a function call, like:
<script>
moduleA
</script>
or this if we want to access a specific property of this member.
<script>
moduleA.someMethod();
</script>
Now, I know there are is gotta be a nicer way of doing this, right? I hate having to have script tags in the HTML modules in order to load its corresponding JS file.
Another limitation of this is the fact that we no longer can work on modules individually, since the scripts and CSS invocation happens on the parent (dashboard.html) so certainly when moduleA.html is loaded directly, it is pure HTML with no script or CSS.
I looked through the other questions but I didn't see anyone with the same problem.
I looked at AngularJS, EmberJS, KO.JS and BoilerPlateJS but none of them addresses what we are trying to accomplish. The only one that has a similar single page concept is jQuery Mobile but I don't know if you can switch from jQuery to jQuery Mobile and everything remains working.
Has anyone face this issue yet? Is there a solution or would I have to go with a custom solution.
Thanks!
I could argue about AngularJS with you. It is exactly what you need
dashboard.html is layout with some directives attached, but power lies in AngularJs if you use ng-view directive
here is example:
dashboard.js
var app = angular.module("modularApp",[]);
app.config(['$routeProvider', "$locationProvider", function routes($routeProvider, $locationProvider) {
$routeProvider.when('/dashboard', {
controller:'HomeCtrl',
templateUrl:'templates/home.html'
});
$routeProvider.when('/moduleA', {
controller:'ModuleACtrl',
templateUrl:'templates/moduleA.html'
});
$routeProvider.when('/moduleB', {
controller:'ModuleBCtrl',
templateUrl:'templates/moduleB.html'
});
$routeProvider.otherwise({redirectTo: "/dashboard"});
}]);
templates/dashboard.html
<html ng-app="modularApp">
<head>
<!--.... include angular minified js file and what else you need...-->
<script type="text/javascript" src="dashboard.js"></script>
<script type="text/javascript" src="moduleACtrl.js"></script>
<script type="text/javascript" src="moduleBCtrl.js"></script>
</head>
<body>
<a ng-href="#/moduleA">Open Module A View</a>
<a ng-href="#/moduleB">Open Module B View</a>
<!-- Add widgets header menus .... -->
<ng-view></ng-view>
</body>
</html>
moduleACtrl.js
var app=angular.module("modularApp");
app.controller("ModuleACtrl",function($scope){
$scope.scopeValue="Hellow from view";
});
moduleBCtrl.js
var app=angular.module("modularApp");
app.controller("ModuleBCtrl",function($scope){
$scope.scopeValue="Hellow from another view";
});
templates/moduleA.html
<div>{{scopeValue}} in module A</div>
templates/moduleB.html
<div>{{scopeValue}} in module B</div>
You can do more complex things with angular then just this. All depends on your needs. Do you have any special requirements :)
Also, you could create your own directive, like ng-view and use your own $route service and $routeProvider so you can add css and javascript you want to dynamically load when some rute match url.
so instead of above routing table, you could have
app.config(['$myRouteProvider', "$locationProvider", function routes($routeProvider, $locationProvider) {
$routeProvider.when('/dashboard', {
javascript:'javascript/dashboard.js',
templateUrl:'templates/dashboard.html',
cssfile: 'css/dashboard.css'
});
$routeProvider.when('/moduleA', {
javascript:'javascript/moduleA.js',
templateUrl:'templates/moduleA.html',
cssfile: 'css/moduleA.css'
});
$routeProvider.when('/moduleB', {
javascript:'javascript/moduleB.js',
templateUrl:'templates/moduleB.html',
cssfile: 'css/moduleB.css'
});
$routeProvider.otherwise({redirectTo: "/dashboard"});
}]);
But that is, pardon on my French, stup. There are couple libs I tried in ruby on rails to acheive similar, but backend is rendering content, or just part of content. But I'm not sure which backend you are using and are you interested to switch to rails anyway.
DomController in BoilerplateJS does what you need, without using any custom HTML attributes. Your dashboard.html can just have place holders where you want to inject your components. I'm just pulling out some html below from BoilerplateJS index.html to show how it works:
<body>
<section id="page-content">
<header>
<section class="theme"></section>
<section class="language"></section>
</header>
<aside>
<section class="main-menu"></section>
</aside>
</section>
</body>
theme, language and main-menu sections above are just place holders in to which relavant components would be injected by the DomController. The DomController can be now used to register the components with appropriate selectors as below:
//scoped DomController that will be effective only on $('#page-content')
var controller = new Boiler.DomController($('#page-content'));
//add routes with DOM node selector queries and relavant components
controller.addRoutes({
".main-menu" : new MainMenuRouteHandler(context),
".language" : new LanguageRouteHandler(context),
".theme" : new ThemeRouteHandler(context)
});
controller.start();
Above code is extracted from "/boilerplatejs/src/modules/baseModule/module.js"

Categories