ondrop ondragover - Uncaught ReferenceError: ondrop is not defined - angular - html5 draggable - angularjs

I try to implement html5 drag and drop with angular.
The code is:
<div ondrop="drop(event)"></div>
And in the controller:
$scope.drop = function(e) { console.log('a drop') };
This leads to the error:
Uncaught ReferenceError: drop is not defined
Exchanging 'ondrop' with 'ng-click' makes it work, so there is nothing missing in the controller.

ondrop is a HTML attribute, therefore it expects the given function to be global, as opposed to angular directives such as ng-click which expect the callbacks to be published on the $scope.

You can use non angular events by connecting functions, that fire in that events to your scope. In this case:
ondrop='angular.element(document.getElementById("Id of element with ngController,or ngView(if you use router)")).scope().drop(event)'
Here I modified the drag and drop example from W3Schools:
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
<style>
#div1, #div2 {
float: left;
width: 100px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
</style>
<body ng-app="myApp">
<div data-ng-controller="myCtrl" id="myContrId">
<div id="div1" ondrop='angular.element(document.getElementById("myContrId")).scope().drop(event)' ondragover='angular.element(document.getElementById("myContrId")).scope().allowDrop(event)'>
<img src="https://diethelper.xyz/DHadmin/images/logo2w.png" draggable="true" ondragstart='angular.element(document.getElementById("myContrId")).scope().drag(event);' id="drag1" width="88" height="31">
</div>
<div id="div2" ondrop='angular.element(document.getElementById("myContrId")).scope().drop(event)' ondragover='angular.element(document.getElementById("myContrId")).scope().allowDrop(event)'></div>
</div>
<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.allowDrop = function(ev) {
ev.preventDefault();
}
$scope.drag = function(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
$scope.drop = function(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
});
</script>
</body>
</html>

ng-click is a directive defined by angular itself. ondrop, is as far as I'm aware not part of angular's standard library. You will need to define a new directive in order to get the functionality you want. I would recommend checking out this blog post
http://blog.parkji.co.uk/2013/08/11/native-drag-and-drop-in-angularjs.html

Related

disabling a div in angularjs using ng-disabled

I wanted to disable a div section using ng-disabled, but it dint work. I've also tried using fieldset in place of div.
ng-disabled seems not working.
Below is the view part:
<div ng-disabled="model.disableDate">
<div>Date</div>
<div ion-datetime-picker ng-model="model.timeEntryDate" ng-change="onTimeEntryDateChange()" date="true" time="false" monday-first="true" am-pm="true">{{model.timeEntryDate|| "Select" | date: "dd/MM/yyyy"}} <i class="icon ion-ios-calendar-outline"></i> </div>
</div>
This is the controller part:
if ($scope.model.pageState === condition) {
$scope.model.disableDate = true;
}
Any way this calender is being popped even on the disabling condition.
You can't disable DIV. Disable work with button and input types only. You can try with css. Use ng-class.
<div ng-class="{ 'div-disabled': model.disableDate}"> // give condition here as per your scenario
.div-disabled
{
pointer-events: none;
opacity: 0.5;
background: #CCC;
}
You can create an attribute directive to disable any div. See below:
var app = angular.module("myApp", []);
app.directive("disableSection", function() {
return {
restrict : "A",
link:function(scope,element,attr,ctrl){
element.css({
cursor :"not-allowed",
opacity: "0.5",
background: "#CCC"
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div disable-section>This is disabled div</div>
</body>
You can use pointer-events: none for disabling the div:-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.obj = {};
$scope.obj.disabled = false;
$scope.clickMe = function(){
alert('div is enabled');
}
});
.disabled {
pointer-events: none;
}
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<div ng-class="(obj.disabled)?'disabled':''" style="width:100px;height:100px;border:1px solid black">
<a style="cursor:pointer" ng-click="clickMe()">Click Me</a>
</div>
<button ng-click="obj.disabled = !obj.disabled">{{(obj.disabled)?'Enable':'Disable'}}</button>
</div>

how to add style in angularjs based on condition in html itself

I have the above page structure . i want to check a conditon to apply style in div with id if the buttonlayout has a class proceed.
<div>
<div id="main">
</div>
<div id='buttonlayout" class="proceed">
</div>
I am displaying the <div id='buttonlayout" class="proceed"></div> based on some conditions. so if the div doesnt exist I dont want to apply sty;e. How can I check this in angular js?
So the logic I am looking for is
if (.div-proceed) exist add an extra style to div (with id main). Is it possible to check in my html page itself (ng-class)?
You can set conditions in ng-class, as sample $scope.proceed default is false our condition is when $scope.proceed is true add class proceed to the element.
This mean if $scope.proceed = false the class not exist, and if it true class is exist.
var app = angular.module("app", []);
app.controller("ctrl", ["$scope", "$filter", function($scope, $filter) {
$scope.change = function() {
$scope.proceed = !$scope.proceed;
}
}]);
body {
padding-top: 50px;
}
a{cursor: pointer}
#buttonlayout {
width: 100px;
height: 100px;
transition: all 0.5s;
background-color: #ccc;
}
#buttonlayout.proceed {
width: 200px;
height: 200px;
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
<a ng-click="change()">click to remove/add 'proceed' class</a>
<div id="buttonlayout" ng-class="{'proceed': proceed}"></div>
</div>

how to dynamically create a div in angular having a certain class?

I want to create a div on click of a button:
the div should be like this:
<div class="my-blur"><div>
I am doing this:
$scope.showFloatingActioButtons = function() {
var newEle = angular.element('<div class="my-blur"></div>');
$compile(newEle)($scope);
}
You are almost there... you just need to add that element to the DOM somehwere.
angular.element('someselector-or-dom-element').append(newEle);
And unless you have bindings or directives on your new element, there is no reason to compile it.
I've added a running example to help clear up any confusion.
var app = angular.module('my-app', []);
function MyCtrl(){}
MyCtrl.prototype = {
addElement:function(){
var newEle = angular.element("<div class='red'></div>");
var target = document.getElementById('target');
angular.element(target).append(newEle);
}
};
app.controller('myCtrl', MyCtrl);
.red{
margin: 10px;
height:20px;
background-color:red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<div ng-app="my-app" ng-controller="myCtrl as $ctrl">
<button type="button" ng-click="$ctrl.addElement()">Add Element</button>
<div id="target"></div>
</div>

Element Directive Not Working

I am using Yeoman so I don't know if it's causing this element directive to not work. So this html template is not showing. I tried using include to see if something was wrong with my code and include worked...so something is going wrong with my directive. Please HELP!
This is my index where I call the directive element:
<div class="announcements">
<div class="announcement-block">
<announcement-block-update></announcement-block-update>
</div>
</div>
This is my javascript:
(function() {
var app = angular.module('announcementApp', [
'ngAnimate',
'ngAria',
'ngCookies',
'ngMessages',
'ngResource',
'ngRoute',
'ngSanitize',
'ngTouch'
]);
app.directive('announcementBlockUpdate',function(){
var announcementsObject = {
type: 'UPDATE',
announcement: 'DISA Maps are almost complete! Look foward to reporting out at the project share next week.'
};
return {
restrict: 'E',
templateUrl: '../views/update-announcement.html',
controller: function(){
this.announcement = announcementsObject;
},
controllerAs: 'announcement'
};
});
})();
This is my HTML template:
<div class="event-highlight update"></div>
<div class="wrap">
<div class="announcement-description">{{announcement.type}}</div>
<div class="announcement">{{announcement.announcement}}</div>
</div>
Your template has an extra closing </div> tag. Not sure if that's related to the problem you're having or not.
Otherwise, your code looks fine. You're initializing the app somewhere in your html, right?
<div class="announcements" ng-app="announcementApp">
TL;DR
Way below is a working code snippet based on what you posted.
Explanation
Instead of trying to specify the controllerAs property, set up two-way databinding between the main controller and the directive scope. This will allow you to simply update the controller (either from a service or resource) and the directive will also update automatically. This is thanks to isolate scopes, which you can learn more about here.
Code
(function() {
var app = angular.module('announcementApp', []);
app.directive('announcementBlockUpdate', function() {
return {
restrict: 'E',
template: '<div class="event-highlight update"></div><div class="wrap"><div class="announcement-description">{{announcement.type}}</div><div class="announcement">{{announcement.announcement}}</div></div>',
scope: {
announcement: '='
}
};
});
app.controller('announcementCtrl', function($scope) {
var announcementsObject = {
type: 'UPDATE',
announcement: 'DISA Maps are almost complete! Look foward to reporting out at the project share next week.'
};
// Change the announcement here...
$scope.announcement = announcementsObject;
});
})();
.announcements {
min-height: 100px;
border: 1px solid #000;
padding: 10px;
}
.announcement-block {
min-height: 20px;
border: 1px solid #333;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="announcementApp">
<div ng-controller="announcementCtrl">
<div class="announcements">
<div class="announcement-block">
<announcement-block-update announcement="announcement"></announcement-block-update>
</div>
</div>
</div>
</div>
Error in your html, the following:
<div class="wrap">
<div class="announcement-description">{{announcement.type}}</div>
<div class="announcement">{{announcement.announcement}}</div>
</div>
should be inside of
<div class="event-highlight update"></div>

How/when to use ng-click to call a route?

Suppose you are using routes:
// bootstrap
myApp.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$routeProvider.when('/home', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
});
$routeProvider.when('/about', {
templateUrl: 'partials/about.html',
controller: 'AboutCtrl'
});
...
And in your html, you want to navigate to the about page when a button is clicked. One way would be
<a href="#/about">
... but it seems ng-click would be useful here too.
Is that assumption correct? That ng-click be used instead of anchor?
If so, how would that work? IE:
<div ng-click="/about">
Routes monitor the $location service and respond to changes in URL (typically through the hash). To "activate" a route, you simply change the URL. The easiest way to do that is with anchor tags.
Go Home
Go to About
Nothing more complicated is needed. If, however, you must do this from code, the proper way is by using the $location service:
$scope.go = function ( path ) {
$location.path( path );
};
Which, for example, a button could trigger:
<button ng-click="go('/home')"></button>
Here's a great tip that nobody mentioned. In the controller that the function is within, you need to include the location provider:
app.controller('SlideController', ['$scope', '$location',function($scope, $location){
$scope.goNext = function (hash) {
$location.path(hash);
}
;]);
<!--the code to call it from within the partial:---> <div ng-click='goNext("/page2")'>next page</div>
Using a custom attribute (implemented with a directive) is perhaps the cleanest way. Here's my version, based on #Josh and #sean's suggestions.
angular.module('mymodule', [])
// Click to navigate
// similar to <a href="#/partial"> but hash is not required,
// e.g. <div click-link="/partial">
.directive('clickLink', ['$location', function($location) {
return {
link: function(scope, element, attrs) {
element.on('click', function() {
scope.$apply(function() {
$location.path(attrs.clickLink);
});
});
}
}
}]);
It has some useful features, but I'm new to Angular so there's probably room for improvement.
Remember that if you use ng-click for routing you will not be able to right-click the element and choose 'open in new tab' or ctrl clicking the link. I try to use ng-href when in comes to navigation. ng-click is better to use on buttons for operations or visual effects like collapse.
But
About
I would not recommend. If you change the route you might need to change in a lot of placed in the application. Have a method returning the link. ex:
About. This method you place in a utility
I used ng-click directive to call a function, while requesting route templateUrl, to decide which <div> has to be show or hide inside route templateUrl page or for different scenarios.
AngularJS 1.6.9
Lets see an example, when in routing page, I need either the add <div> or the edit <div>, which I control using the parent controller models $scope.addProduct and $scope.editProduct boolean.
RoutingTesting.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testing</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular-route.min.js"></script>
<script>
var app = angular.module("MyApp", ["ngRoute"]);
app.config(function($routeProvider){
$routeProvider
.when("/TestingPage", {
templateUrl: "TestingPage.html"
});
});
app.controller("HomeController", function($scope, $location){
$scope.init = function(){
$scope.addProduct = false;
$scope.editProduct = false;
}
$scope.productOperation = function(operationType, productId){
$scope.addProduct = false;
$scope.editProduct = false;
if(operationType === "add"){
$scope.addProduct = true;
console.log("Add productOperation requested...");
}else if(operationType === "edit"){
$scope.editProduct = true;
console.log("Edit productOperation requested : " + productId);
}
//*************** VERY IMPORTANT NOTE ***************
//comment this $location.path("..."); line, when using <a> anchor tags,
//only useful when <a> below given are commented, and using <input> controls
$location.path("TestingPage");
};
});
</script>
</head>
<body ng-app="MyApp" ng-controller="HomeController">
<div ng-init="init()">
<!-- Either use <a>anchor tag or input type=button -->
<!--Add Product-->
<!--<br><br>-->
<!--Edit Product-->
<input type="button" ng-click="productOperation('add', -1)" value="Add Product"/>
<br><br>
<input type="button" ng-click="productOperation('edit', 10)" value="Edit Product"/>
<pre>addProduct : {{addProduct}}</pre>
<pre>editProduct : {{editProduct}}</pre>
<ng-view></ng-view>
</div>
</body>
</html>
TestingPage.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.productOperation{
position:fixed;
top: 50%;
left: 50%;
width:30em;
height:18em;
margin-left: -15em; /*set to a negative number 1/2 of your width*/
margin-top: -9em; /*set to a negative number 1/2 of your height*/
border: 1px solid #ccc;
background: yellow;
}
</style>
</head>
<body>
<div class="productOperation" >
<div ng-show="addProduct">
<h2 >Add Product enabled</h2>
</div>
<div ng-show="editProduct">
<h2>Edit Product enabled</h2>
</div>
</div>
</body>
</html>
both pages -
RoutingTesting.html(parent), TestingPage.html(routing page) are in the same directory,
Hope this will help someone.
Another solution but without using ng-click which still works even for other tags than <a>:
<tr [routerLink]="['/about']">
This way you can also pass parameters to your route: https://stackoverflow.com/a/40045556/838494
(This is my first day with angular. Gentle feedback is welcome)
You can use:
<a ng-href="#/about">About</a>
If you want some dynamic variable inside href you can do like this way:
<a ng-href="{{link + 123}}">Link to 123</a>
Where link is Angular scope variable.
just do it as follows
in your html write:
<button ng-click="going()">goto</button>
And in your controller, add $state as follows:
.controller('homeCTRL', function($scope, **$state**) {
$scope.going = function(){
$state.go('your route');
}
})

Resources