I want to use this tinyColorPicker plugin https://github.com/PitPik/tinyColorPicker but it's proving extremely difficult to use it in my angular app.
I keep getting this error:
TypeError: element.colorPicker is not a function
In my index.html
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/tinycolorpicker/lib/jquery.tinycolorpicker.js"></script>
I have then made a directive to instantiate the plugin
'use strict';
angular.module('myApp')
.directive('colorWheel', function() {
return {
restrict: 'A',
link: function(scope, element) {
element.colorPicker();
}
};
});
And in my HTML I have this div with the directive
<div id="colorWheel" color-wheel></div>
According to their docs that is all I have to do. I must be missing something key when it comes to integrating it with Angular. Can anyone see anything? Thanks
Element is not a jQuery object, it is an angular object. The plugin is is exposed on the jQuery object. Try using jQuery selectors in your link fn e.g. jQuery("#yourDomId").colorPicker()
You have to load jQuery before you loading angularjs.
If you will load jquery after loading angular you will get the jqLite.
<script src="jquery.js"></script>
<sciprt src="angular.js"></script>
Related
I am trying to lazy load a directive within another directive based on a condition. I have a main directive and within it I have a <script> tag. The included directive loads properly only when jquery is present, the problem is that not all of my pages load jquery. There is also a second warning...
synchronous XMLHttpRequest on the main thread is deprecated.
Which I should be able to suppress if I find a pure angularJs way of loading the script.
Here is my setup
<my-directive>
<script ng-if="expression" src="../path" type="application/javascript"></script>
</my-directive>
very simple, but it only works if jquery is there to load it. I tried to load it via $http.get() request and then eval() (which I know the dangers) but that did not work.
Here is a way which leverages the $http approach. You can create a directive which augments your <script> tag for this functionality, checking for a defined type attribute. You could of course modify this check however you'd like. Observe the following...
app.directive('script', function($http) {
return {
restrict: 'E',
scope: false,
link: function(scope, elem, attrs) {
if (attrs.type === 'text/javascript-lazy') {
$http.get(attrs.src).then(function(response) {
var code = response.data;
var f = new Function(code);
f();
});
}
}
};
});
<!-- retrieved -->
<script type="text/javascript-lazy" ng-if="true" src="script.js"></script>
<!-- not retrieved -->
<script type="text/javascript-lazy" ng-if="false" src="script.js"></script>
This will work inside an element wrapped directive as well.
Plunker - working demo
In a thirth party framework, A html page can be modified by providing javascript code that will be added by the framework to the window onload. From their content can be written to the AddIn div element.
How could I inject a angular application into this div element (HTML + js).
<!DOCTYPE html>
<html>
<head>
<script src="http://apps.bdimg.com/libs/angular.js/1.4.0-beta.4/angular.min.js"></script>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script type="text/javascript">
window.onload=function() {
//todo add js code here
}
</script>
</head>
<body>
<div id="AddIn"></div>
</body>
</html>
I can add the html
$('#AddIn').append("<div ng-app='dropboxApp' ng-controller='dropboxController as dropbox'>{{dropbox.label}}</div>");
but I am not sure where to add my angular init code, and get things working
angular.module('dropboxApp', [])
.controller('dropboxController', function () {
var dropbox = this;
dropbox.label = 'hello angular';
});
You could lazily initialize your app on the page instead of using ng-app directive on page. After you html injection you could initialize angular on your page using angular.bootstrap method basically which takes DOM & then inside array it needs module name.
While doing this you need to add your all the angular component files on the page itself after angular reference. They should be initialized before you bootstrap the app on the page.
window.onload=function() {
$('#AddIn').append("<div ng-controller='dropboxController as dropbox'>{{dropbox.label}}</div>");
//add angular html first
//then run angular on the page using angular.bootstrap.
angular.bootstrap($('#AddIn'), ['demo']);
}
Note: Load jQuery before angular to get jQuery compiled DOM instead of get jQLite compiled DOM.
In addition to the Pankaj answer, you can use the Angular $window
$window.onload = function (){}
I have this current app.js
angular.module('app', ['ngRoute', 'ngSanitize', 'ui.bootstrap','ui.router', 'com.2fdevs.videogular', 'com.2fdevs.videogular.plugins.controls', 'com.2fdevs.videogular.plugins.overlayplay',
'com.2fdevs.videogular.plugins.poster', 'com.2fdevs.videogular.plugins.buffering', 'ngDraggable','angular-loading-bar', 'chart.js', 'angularSpinner'])
and I include the needed javascript files in my index.html
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-resource.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-route.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-sanitize.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.1/ui-bootstrap-tpls.min.js"></script>
With this, the carousel is working at least, there is no transition animation, but if I click on the arrow it switches to the next one.
then I added the angular-animate to the index.html:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular-animate.js"></script>
and ngAnimate to the app.js as dependency.
But this break the carousel. With this, the carousel won't go forward on its own and a click on the arrow will do nothing. I do not see any errors in the console and not at all why this is not working. Am I missing some css stuff or what?
May be a little late here, but there is a solution to this. Make a directive which essentially disables ng-animate:
app.directive('disableAnimation', function ($animate) {
return {
restrict: 'A',
link: function ($scope, $element, $attrs) {
$attrs.$observe('disableAnimation', function (value) {
$animate.enabled(!value, $element);
});
}
}
});
Then add attribute "disable-animation='true'" to your carousel tag. This solution was suggested by another user on a different question. I'm trying desperately to find him and give him the credit he deserves, I'll make an edit if I locate it.
However after writing up a few examples to play around with the controllers would not load. I was getting an error:
firstController is not a function
After some googling I found that Angular 1.3.x no longer supports global controllers. All the examples I have seen of the new way of creating controllers seem to create them in my app.js file. I am confused, does this now mean that I must create all my controllers here rather than having a dedicated file for each controller. I have tried this to create the controller and still no luck:
UPDATE: I changed my controller to match jedanput's answer but changed $scope to this.
app.controller('firstController', [function(){
this.name = "Tim";
}]);
Also I find it very annoying that all that the majority of the example out there still reference the way it was done in Angular 1.2.
Any help would be greatly appreciated as I am having trouble understanding this issue.
EDIT: Here is my index.html file. Hopefully this will help you guys understand what is going wrong.
<!DOCTYPE html>
<html lang="en" xmlns:ng="http://angularjs.org" id="ng-app" ng-app="myApp">
<head >
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>ControllerAs</title>
<meta name="description" content="">
</head>
<body>
<div class="content" ng-view=""></div>
<!-- jQuery -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<!-- AngularJS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.6/angular-route.js"></script>
<script type="text/javascript" src="../js/app.js"></script>
<!--Directives-->
<script type="text/javascript" src="../js/directives/it-works.js"> </script>
<!--Controllers-->
<script type="text/javascript" src="../js/controllers/firstController.js"></script>
<script type="text/javascript" src="../js/controllers/secondController.js"></script>
</body>
</html>
So far I have avoided Controllers as everything I have been doing could be done with directives and services but it is time I understood more about controllers. I think it may be something fundamental I am missing. Again any help is greatly appreciated.
UPDATE: still getting the same error. This is my app.js file. Maybe it can shed some light on the problem.
var app = angular.module('myApp',[
'ngRoute'
]);
app.config(function($routeProvider) {
$routeProvider.when('/', {
templateUrl: "../partials/test-skeleton.html"
})
});
It should be
app.controller('firstController', ['$scope', function($scope){
$scope.name = "Tim";
}]);
Also, controllerAs syntax is synthetic sugar for the scope simply, you avoid using this:
<div ng-controller="oneCtrl">
{{name}}
</div>
And instead use this:
<div ng-controller="oneCtrl as one">
{{one.name}}
</div>
Which helps tremendously when you have nested controllers.
You're right, Angular allows for multiple different notations and that can be annoying and confusing. I would recommend you to stick with the guidelines from John Papas Angular Style Guide. He uses this:
(function() {
'use strict';
// Get reference to your application
angular.module('myapp')
// Add the controller
.controller('mycontroller',controller);
// This makes the injection of the controller arguments
// explicit
controller.$inject = ['$scope', '$http'];
// Here the actual controller is defined - where
// the arguments are injected on the same location as
// in the previous array
function controller($scope, $http) {
// Controller logic
});
})();
You want to keep stuff out of the global space. Really - you do. That's why he wraps everything in an Immediately-Invoked Function Expression (IIFE).
Also - you want to explicitly define what you're injecting ( the $inject array ). If not, you will not be able to minify later.
So I'm sorry - I just added another way of defining your AngularJS artefacts. From what I understand, this is one the more well known style guides out there. I've heard that he's working closely with the Angular guys to make sure his style guide will also make it easier to transition to the new Angular version.
And no - you do not need to put everything in 1 file - just make sure you have a file with angular.module('myapp',[]) loaded before any of the other files. This will declare the myapp module and will append the controller to it.
As I'm writing this - I realize that there's also another way: you create a new module in this file, append the controller and then load that module into your application. But yeah ... it's confusing.
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