Refreshing App State on Child Component Change - javascript

I have a list of elements. When I click an up or down icon, I would like the list to rearrange itself and, finally, for the app to rerender itself so I can see the change reflected in the DOM.
Changing list position works. I'm running into issues when I try to run the refreshState method. I'm passing the function as a property of the child but calling that property returns undefined function.
Q: How do I call a component's method from its child component?
Code:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<script src="http://fb.me/react-with-addons-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
</head>
<body>
<style>
/* CSS */
span {
margin:0 0 0 10px;
}
</style>
<div id="app"></div>
<script type="text/jsx">
// React
var _data = ['Red', 'Blue', 'Green'];
function getState() {
return {
colors: _data,
}
};
Array.prototype.swap = function(a, b) {
var temp = this[a];
this[a] = this[b];
this[b] = temp;
};
var App = React.createClass({
getInitialState: function() {
return getState();
},
render: function() {
var colors = this.state.colors.map(function(color) {
return (
<Color name={color} refreshState={this.refreshState} />
)
});
return (
<ul>{colors}</ul>
)
},
refreshState: function() {
return this.setState(getState());
},
});
var Color = React.createClass({
moveUp: function() {
var current = _data.indexOf(this.props.name),
above = current - 1;
if (above >= 0) {
_data.swap(current, above);
}
return this.props.refreshState();
},
moveDown: function() {
var current = _data.indexOf(this.props.name),
below = current + 1;
if (below < _data.length) {
_data.swap(current, below);
}
return this.props.refreshState();
},
render: function() {
return (
<li>
<strong>{this.props.name}</strong>
<span onClick={this.moveUp}>^</span>
<span onClick={this.moveDown}>v</span>
</li>
)
},
});
React.render(<App />, document.getElementById('app'));
</script>
</body>
</html>

Noticed you have solved the question, but thought I'd mention that you can pass a scope to .map which means no need to cache scope for the purpose you describe:
this.state.colors.map(function(color) {
return (
<Color
key={_data.indexOf(color)}
name={color}
refresh={this.refreshState}
/>
)
}, this); // pass the scope to .map

I was trying to call this.refreshState within the map method. This, of course, does not have the same scope as the render method. The solution was to store the scope in a variable:
var refresh = this.refreshState;
Then use that variable within the map method:
... refreshState={refresh} ...
Always be aware of your scope!
If you have multiple functions that aren't within the local scope then you can store this in a variable.
var self = this;
z.map(function(arg) {
x={self.refreshState} y={self.otherThing}
And for the curious, the finished result:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Test</title>
<script src="http://fb.me/react-with-addons-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
</head>
<body>
<style>
/* CSS */
span {
margin:0 0 0 10px;
}
</style>
<div id="app"></div>
<script type="text/jsx">
// React
var _data = ['Red', 'Blue', 'Green'];
function getState() {
return {
colors: _data,
}
};
Array.prototype.swap = function(a, b) {
var temp = this[a];
this[a] = this[b];
this[b] = temp;
};
var App = React.createClass({
getInitialState: function() {
return getState();
},
refreshState: function() {
return this.setState(getState());
},
render: function() {
var self = this;
var colors = this.state.colors.map(function(color) {
return (
<Color
key={_data.indexOf(color)}
name={color}
refresh={self.refreshState}
/>
)
});
return (
<ul>{colors}</ul>
)
},
});
var Color = React.createClass({
propTypes: {
name: React.PropTypes.string,
refresh: React.PropTypes.func.isRequired,
},
moveUp: function() {
var current = _data.indexOf(this.props.name),
above = current - 1;
if (above >= 0) {
_data.swap(current, above);
}
return this.props.refresh();
},
moveDown: function() {
var current = _data.indexOf(this.props.name),
below = current + 1;
if (below < _data.length) {
_data.swap(current, below);
}
return this.props.refresh();
},
render: function() {
return (
<li>
<strong>{this.props.name}</strong>
<span onClick={this.moveUp}>^</span>
<span onClick={this.moveDown}>v</span>
</li>
)
},
});
React.render(<App />, document.getElementById('app'));
</script>
</body>
</html>

Related

Javascript addEventListener passing function pointer

i like to pass to a function pointer to function that the addEventListener will use .
if you run this you will get an error .
what is the "Javascript" way to pass a function pointer ( don't know how to call it ) to addEventListener ?
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="UTF-8">
<title>Title</title>
<style>
</style>
<script>
var data = {
"foo1" : "aaa",
"foo2" : "bbb",
"foo3" : "ccc"
}
var createLabel = function(mykey,func) {
var label = document.createElement('label');
label.innerHTML = mykey;
label.id = "lbl_"+mykey;
label.addEventListener("click", () =>{
self.func(mykey);
}, false);
document.getElementById("container2").appendChild(label);
var br = document.createElement('br');
document.getElementById("container2").appendChild(br);
};
var popolateDS = function() {
self = this;
var i = 0;
for(var key in data) {
(function () {
var mykey = key;
if (data.hasOwnProperty(key)) {
if(i==0) {
createLabel(key,dsOnClick1);
i++;
}
createLabel(key,dsOnClick2);
}
}()); // immediate invocation
}
}
var dsOnClick1 = function(key) {
alert("dsOnClick1 "+key);
}
var dsOnClick2 = function(key) {
alert("dsOnClick2 "+key);
}
</script>
</head>
<body>
<div id="container2">
</div>
<button onclick="popolateDS()">click</button>
</body>
</html>
You don't need to refer to this as self.func, you can just call func like below and it'll work as expected:
label.addEventListener("click", () =>{
func(mykey);
}, false);

Update JS model through MVC not change

i have variables as a model, i were able to change it temporary but when try to update other values it's fetched in the controller but when try to re render it again it show the new value and retrieve the old value quickly,
the issue in updateCat func i think, also i want to pass form is object not each value alone as updated-name and updated-img.
Thanks in advance.
/* ======= Model ======= */
var model = {
currentCat: null,
cats: [
{
clickCount: 0,
name: 'Tabby',
imgSrc: 'img/434164568_fea0ad4013_z.jpg',
imgAttribution: 'https://www.flickr.com/photos/bigtallguy/434164568',
isAdmin: 0
},
{
clickCount: 0,
name: 'Tiger',
imgSrc: 'img/4154543904_6e2428c421_z.jpg',
imgAttribution: 'https://www.flickr.com/photos/xshamx/4154543904',
isAdmin: 0
},
{
clickCount: 0,
name: 'Scaredy',
imgSrc: 'img/22252709_010df3379e_z.jpg',
imgAttribution: 'https://www.flickr.com/photos/kpjas/22252709',
isAdmin: 0
},
{
clickCount: 0,
name: 'Shadow',
imgSrc: 'img/1413379559_412a540d29_z.jpg',
imgAttribution: 'https://www.flickr.com/photos/malfet/1413379559',
isAdmin: 0
},
{
clickCount: 0,
name: 'Sleepy',
imgSrc: 'img/9648464288_2516b35537_z.jpg',
imgAttribution: 'https://www.flickr.com/photos/onesharp/9648464288',
isAdmin: 0
}
]
};
/* ======= Octopus ======= */
var octopus = {
init: function () {
// set our current cat to the first one in the list
model.currentCat = model.cats[0];
// tell our views to initialize
catViewList.init();
catView.init();
},
getCurrentCat: function () {
return model.currentCat;
},
getCats: function () {
return model.cats;
},
// set the currently-selected cat to the object passed in
setCurrentCat: function (cat) {
model.currentCat = cat;
},
// increments the counter for the currently-selected cat
incrementCounter: function () {
model.currentCat.clickCount++;
catView.render();
},
// Admin mode, to edit exist cat (name, url)
showAdminForm: function () {
model.currentCat.isAdmin = 1;
catView.render();
},
updateCat: function (name, img) {
console.log(name + " ----- " + img + " before currentCat " + model.currentCat.name);
model.currentCat.name = name;
model.currentCat.imgSrc = img;
catView.render();
}
};
/* ======= View ======= */
var catView = {
init: function () {
// POINTERS
this.catElem = document.getElementById('cat-div');
this.catNameElem = document.getElementById('cat-name');
this.catCounter = document.getElementById('cat-counter');
this.catImage = document.getElementById('cat-image');
this.isAdmin = document.getElementById('show-admin');
this.adminPanel = document.getElementById('admin-panel');
this.newName = document.getElementById('updated-name');
this.newImg = document.getElementById('updated-name');
this.isAdmin.addEventListener('click', function () {
octopus.showAdminForm();
});
this.catImage.addEventListener('click', function () {
// Get count from octopus
octopus.incrementCounter();
});
this.render();
},
render: function () {
// Empty the form
// this.isAdmin.innerHTML = '';
// update the DOM elements with values from the current cat
var currentCat = octopus.getCurrentCat();
this.catCounter.textContent = currentCat.clickCount;
this.catNameElem.textContent = currentCat.name;
this.catImage.src = currentCat.imgSrc;
this.isAdmin = currentCat.isAdmin;
this.newName.textContent = currentCat.name;
this.newImg.src = currentCat.imgSrc;
this.adminPanel.addEventListener('submit', function() {
var updatedName = document.getElementById("updated-name").value;
var updatedImg = document.getElementById("updated-img").value;
// document.getElementById('cat-name') = updatedName;
octopus.updateCat(updatedName, updatedImg);
// catView.render();
});
if (this.isAdmin == 1) {
this.adminPanel.style.display = "block";
// problem here when changed and re render it fetched old name
// this.adminPanel.addEventListener('submit', function() {
// var updatedName = document.getElementById("updated-name").value;
// var updatedImg = document.getElementById("updated-img").value;
// console.log(updatedName + updatedImg);
// // document.getElementById('cat-name') = updatedName;
// octopus.updateCat(updatedName, updatedImg);
// // catView.render();
// });
} else {
this.adminPanel.style.display = "none";
}
}
};
var catViewList = {
init: function () {
// store the DOM element for easy access later
this.catListElem = document.getElementById('side_nav_item');
// render this view (update the DOM elements with the right values)
this.render();
},
render: function () {
var cat, elem, i;
// get the cats we'll be rendering from the octopus
var cats = octopus.getCats();
// empty the cat list
this.catListElem.innerHTML = '';
// loop over the cats
for (i = 0; i < cats.length; i++) {
// this is the cat we're currently looping over
cat = cats[i];
// make a new cat list item and set its text
elem = document.createElement('a');
elem.textContent = cat.name;
// on click, setCurrentCat and render the catView
// (this uses our closure-in-a-loop trick to connect the value
// of the cat variable to the click event function)
elem.addEventListener('click', (function (catCopy) {
return function () {
octopus.setCurrentCat(catCopy);
catView.render();
};
})(cat));
// finally, add the element to the list
this.catListElem.appendChild(elem);
}
}
};
octopus.init();
<!DOCTYPE html>
<html lang="en">
<head>
<link href="css/main.css" rel="stylesheet">
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"> -->
<title>Cat List </title>
</head>
<body>
<div class="main">
<div id="side_nav" class="sidenav" >
<li id="side_nav_item" class="side_nav_item"></li>
</div>
<div id="cat-div">
<h2 id="cat-name"></h2>
<div id="cat-counter"></div>
<img id="cat-image" src="" alt="cute cat">
</div>
<button id="show-admin">Admin</button>
<form id="admin-panel">
<label >Name :</label>
<input type="text" id="updated-name">
<label>Img url :</label>
<input type="text" id="updated-img">
<button id="updateCat" type="submit">Save</button>
</form>
<script src="js/model.js"></script>
</div>
</body>
</html>
I found the solution for my silly issue,
this.adminPanel.addEventListener('submit', function(evt) {
var nameToChange = document.getElementById('updated-name').value;
var imgTOChange = document.getElementById('updated-img').value;
console.log(nameToChange + imgTOChange);
octopus.updateCat(nameToChange + imgTOChange);
evt.preventDefault(); // Here is the trick
});
to close.
Thanks.

How do i use ArcGIS Maps in Angular-Js?

How do i use ArcGIS Maps in Angular-Js easily with manipulating the;
zoom
locate
adding markers
search my places by Geo coordinates and Place name
loading markers lazily and the like?
Can some one Give me a sample please.
This website has many examples and sample code:
http://esri.github.io/angular-esri-map/#/home
Well, Below is the sample to load ArcGIS/ESRI map using angular-js and for more details and relevance sample/concept read getting-started from below mentioned link:
<!DOCTYPE html>
<html ng-app="esri-map-example">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>Angular Esri Quick Start</title>
<link rel="stylesheet" href="//js.arcgis.com/4.0/esri/css/main.css">
<style type="text/css">
html, body, .esri-view {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
</head>
<body ng-controller="MapController as vm">
<esri-scene-view map="vm.map" view-options="{scale: 50000000, center: [-101.17, 21.78]}">
</esri-scene-view>
<!-- load Esri JSAPI -->
<script src="//js.arcgis.com/4.0/"></script>
<!-- load AngularJS -->
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<!-- load angular-esri-map -->
<script src="//unpkg.com/angular-esri-map#2"></script>
<script type="text/javascript">
angular.module('esri-map-example', ['esri.map'])
.controller('MapController', function(esriLoader) {
var self = this;
esriLoader.require(['esri/Map'], function(Map) {
self.map = new Map({
basemap: 'streets'
});
});
});
</script>
</body>
</html>
More more details please click here...
Hoping this will help you to understand and start your implementation :)
I came across a very simple way of adding all the mentioned features and be able to control them in this way.
angular.module('eBlood').directive('esriPointRenderersMap', ['$q', 'appConfig', 'esriLoader', 'esriRegistry', function($q, appConfig, esriLoader, esriRegistry) {
return {
// element only directive
restict: 'E',
// isolate the scope
scope: {
// 1-way string binding
rendererActive: '#',
// 2-way object binding
basemapActive: '=',
clusterTolerance: '=',
heatmapRendererParams: '='
},
compile: function($element, $attrs) {
// remove the id attribute from the main element
$element.removeAttr('id');
// append a new div inside this element, this is where we will create our map
$element.append('<div id=' + $attrs.id + '></div>');
// since we are using compile we need to return our linker function
// the 'link' function handles how our directive responds to changes in $scope
// jshint unused: false
return function(scope, element, attrs, controller) {};
},
controller: function($scope, $element, $attrs) {
var mapDeferred = $q.defer();
var esriApp = {};
// add this map to the registry
if ($attrs.registerAs) {
var deregister = esriRegistry._register($attrs.registerAs, mapDeferred.promise);
// remove this from the registry when the scope is destroyed
$scope.$on('$destroy', deregister);
}
esriApp.createGeoCordFinder = coords => {
return esriLoader.require([
'esri/geometry/Point',
'esri/tasks/Locator'
]).then(x => {
var Point = x[0];
if (!esriApp.mapLocator) {
var Locator = x[1];
esriApp.mapLocator = new Locator('https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer');
}
return esriApp.mapLocator.locationToAddress(new Point(coords)).then(res => {
return res.address.Match_addr;
});
});
};
esriApp.zoomToLocation = mapOptions => {
if (mapOptions.view) {
mapOptions.zoom = mapOptions.zoom || appConfig.pointRenderers.mapOptions.zoom;
mapOptions.view.goTo({
target: [mapOptions.coordinates.longitude, mapOptions.coordinates.latitude],
zoom: mapOptions.zoom
});
// change the marker to the current Geo.
var promise = (!mapOptions.address) ? esriApp.createGeoCordFinder(mapOptions.coordinates) : $q.when(mapOptions.address);
promise.then(location => {
esriApp.changeLocationMarker({
view: mapOptions.view,
attributes: {
address: location
},
geometry: {
longitude: mapOptions.coordinates.longitude,
latitude: mapOptions.coordinates.latitude
}
});
});
}
};
esriApp.createLocateIcon = mapOptions => {
var container;
if (!mapOptions || !mapOptions.view)
return $q.reject('Our MapView is setYet');
container = mapOptions.container |"map";
mapOptions.container = undefined;
mapOptions.goToLocationEnabled = appConfig.goToLocationEnabled;
mapOptions.graphic = null;
return esriLoader.require([
'esri/widgets/Locate'
]).then(x => {
var Locate = x[0];
esriApp.locateWidget = new Locate(mapOptions, container);
esriApp.locateWidget.startup();
if (!container)
mapOptions.view.ui.add(esriApp.locateWidget, 'top-left');
esriApp.locateWidget.on('locate', data => {
esriApp.zoomToLocation({
view: mapOptions.view,
coordinates: data.position.coords
});
});
return esriApp.locateWidget;
});
};
function setSearchWidget(opts) {
var srcNodeRef;
if (!opts || !opts.view) {
return $q.reject('MapView is undefined');
}
srcNodeRef = opts.container;
opts.container = undefined;
opts.showPopupOnSelect = false;
opts.autoSelect = false;
return esriLoader.require([
'esri/widgets/Search'
]).then(x => {
var Search = x[0];
var searchWidget = new Search(opts, srcNodeRef);
searchWidget.startup();
if (!srcNodeRef) {
opts.view.ui.add(searchWidget, 'top-right');
}
searchWidget.on('search-complete', e => {
if (e.results.length > 0 && e.results[0].results.length > 0) {
var res = e.results[0].results[0];
var coords = {
longitude: res.feature.geometry.longitude,
latitude: res.feature.geometry.latitude
};
esriApp.zoomToLocation({
view: opts.view,
coordinates: coords,
address: res.name
});
}
});
return searchWidget;
});
}
var mapoption = {
map: esriApp.map,
container: 'map',
zoom: 3,
padding: {
top: 65
},
view: esriApp.mapView
};
esriApp.buildmap = (mapViewDiv) => {
return esriApp.creatMap({
basemap: $scope.basemapActive
})
.then(map => {
mapoption.map = map;
mapoption.container = mapViewDiv;
return esriApp.createMapView(mapoption);
});
};
esriApp.creatMap = properties => {
return esriLoader.require(['esri/Map'])
.then(esriModules => {
var Map = esriModules[0];
return new Map(properties);
});
};
esriApp.createMapView = config => {
return esriLoader.require(['esri/views/MapView'])
.then(x => {
var MapView = x[0];
esriApp.mapView = new MapView(config);
mapDeferred.resolve({
view: esriApp.mapView
});
return mapDeferred.promise;
});
};
esriApp.map = esriApp.buildmap($attrs.id);
mapoption.view = esriApp.mapView;
esriApp.createLocateIcon(mapoption);
setSearchWidget(mapoption);
mapDeferred.promise.then(function(esriApp) {
// clean up
$scope.$on('$destroy', function() {
esriApp.map.destroy();
});
});
// });
}
};
}]);
The simple directive will be very use full. More so now that it updates the 'appConfig' global config object with the map features. This worked very well for me.
Thanks Guys for you contributions.

update $scope from service property in angularJS

I'm new in AngularJS and i'd like to know why, in the next piece of code, the "randomN" property of the service is not updating at the $scope.
Since i'm taking a reference to the object's service at the controller with
$scope.srvRandom = srvRandom;
Why changes at srvRandom.randomN are not taking effect?
I think the problem is that "randomN" takes the value of "r" and not a reference to it, but i don't know how to make it work.
var app = angular.module("app", []);
app.controller("cont", ['$scope','srvRandom', function ($scope, srvRandom) {
$scope.srvRandom = srvRandom;
}]);
app.factory("srvRandom", ["$interval", function ($interval) {
var randomCreator;
var r;
return {
start: function () {
console.log("START")
randomCreator = $interval(function () {
r= Math.random() * 10;
}, 2000);
},
stop: function () {
console.log("STOP")
$interval.cancel(randomCreator);
},
randomN: r
};
}]);
HTML:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.0-rc.2/angular.min.js"></script>
<script src="test.js"></script>
</head>
<body ng-app="app" ng-controller="cont">
RandomNumber: {{srvRandom.randomN}}
<div>
<button ng-click="srvRandom.start()">START!</button>
<button ng-click="srvRandom.stop()">STOP!</button>
</div>
</body>
</html>
Thank you!
You are accessing srvRandom.randomN which is always 0.
...
randomN: 0
...
I think you should do
app.factory("srvRandom", ["$interval", function ($interval) {
var randomCreator,
randomN = 0; // Change
return {
start: function () {
console.log("START")
randomCreator = $interval(function () {
randomN = Math.random() * 10;
}, 2000);
},
stop: function () {
console.log("STOP")
$interval.cancel(randomCreator);
},
randomN: randomN // Change
};
}]);
just update your start method to use this for current object not window object.
start: function() {
var that = this; //store this reference to a variable
randomCreator = $interval(function() {
that.randomN = Math.random() * 10; // use here
}, 2000);
},
doing this $scope.Random = srvRandom; create a local instance of the service obj
var app = angular.module("app", []);
app.controller("cont", ['$scope', 'srvRandom',
function($scope, srvRandom) {
$scope.random = 0;
$scope.$watch('getRandom()',function(newv){
$scope.random = newv;
});
$scope.start = function(){
srvRandom.start();
}
$scope.stop = function(){
srvRandom.stop();
}
$scope.getRandom = function(){
return srvRandom.getRandom();
}
}
]);
app.factory("srvRandom", ["$interval",
function($interval) {
var randomCreator;
var randomN = 0;
return {
start: function() {
console.log("START")
randomCreator = $interval(function() {
randomN = Math.random() * 10;
}, 2000);
},
stop: function() {
console.log("STOP")
$interval.cancel(randomCreator);
},
getRandom: function() {
return randomN;
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app" ng-controller="cont">
RandomNumber: {{random}}
<div>
<button ng-click="start()">START!</button>
<button ng-click="stop()">STOP!</button>
</div>
</body>

Drag and drop with AngularJS, Javascript and HTML doesn't work

I researched much, but I didn't get the answer.
At the moment I'm learning Angular and javascript and so I'm building a todo-app with HTML, Javascript and (of course) Angular. I want to have a drag and drop system... so if you want to delete a task you drag it and drop it into the trash.
I managed to build a drag and drop system with HTML and Javascript, but I don't get it to combine it with my angular code.
Take a look on it by yourself:
my HTML-code (and Javascript). You can drag and drop the things,but the functionality (so if you move a task to the trash it will be deleted) doesn't work (because therefor I need Angular). :
<!DOCTYPE html>
<html ng-app="todoApp">
<head>
<title>ToDo</title>
<link rel="stylesheet" href="style.css">
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
function trashdrop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body >
<div ng-controller="Tasks as tasksCtrl">
<div class="background" ng-dblclick="close()" ondrop="drop(event)" ondragover="allowDrop(event)">
...
<div id ="$index"class="ng-class: task.classe" ng-repeat="task in tasks | orderBy:sortBy:reverse" ng-click="setEditId($index)" draggable="true" ondragstart="drag(event)" >
<img ng-src="{{task.group.image}}" width="30px" height="30px" align="right" style="margin-right: 30%">
<div style="padding: 20px">{{task.title}}</br>{{task.body}} {{task.dueDate}}</div>
</div>
...
<img src="bigtrash.png" class="trash" ondrop="trashdrop(event)" ondragover="allowDrop(event)">
</div>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
<!-- <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular-animate.js"></script> -->
<script type="text/javascript" src="app.js"></script>
</body>
</html>
and here is my javascript:
var todoApp = angular.module('todoApp', [])
todoApp.factory('TasksService', function () {
var steps = [];
var tasks = [];
var groups = [];
return {
getTasks: function () {
return tasks;
},
deleteTask: function (id) {
tasks.splice(id-1, 1);
},
getGroups: function () {
return groups;
},
getSteps: function () {
return steps;
},
getStepsId: function (id) {
return steps[id];
},
getGroupId: function (name) {
for (var i = 0; i < groups.length; i++) {
if(groups[i].name===name) {
return i;
}
};
return undefined;
},
addTask:function (task) {
tasks.push(task);
},
addStep:function (step, id) {
steps[id].push(step);
tasks[id].steps=steps[id];
},
addStepGroup:function () {
steps.push([]);
},
setTasks:function (filterdTasks) {
tasks = filterdTasks;
console.log("tasks", tasks);
},
addGroup: function (group) {
groups.push(group);
}
}
});
todoApp.controller('Tasks', function($scope, TasksService) {
var status = "done";
var priority = "3"
$scope.groups = TasksService.getGroups();
$scope.edit = false;
$scope.specedit = false;
$scope.id = null;
$scope.newgroup = false;
$scope.tasks = TasksService.getTasks();
//the drag and drop functions
$scope.allowDrop = function(ev) {
ev.preventDefault();
}
$scope.drag = function(ev) {
console.log(ev.target);
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));
}
$scope.trashdrop = function(ev) {
ev.preventDefault();
TasksService.deleteTask(ev.target.id);
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
}
$scope.setEdit = function() {
$scope.edit = true;
}
$scope.setEditId = function(id) {
$scope.specedit = true;
$scope.id = id;
}
$scope.deleteTask = function(id) {
TasksService.deleteTask(id);
}
$scope.close = function() {
console.log("hi");
$scope.specedit = false;
$scope.edit = false;
$scope.id = null;
$scope.newgroup = false;
}
$scope.newGroup = function() {
$scope.newgroup = true;
}
this.addTask = function(title, body, group, date) {
$scope.edit = false;
TasksService.addTask({
id: $scope.tasks.length,
title: title,
body: body,
dueDate: date,
status: status,
group: {name: group, color: TasksService.getGroups()[TasksService.getGroupId(group)].color, image: TasksService.getGroups()[TasksService.getGroupId(group)].image,},
priority: priority,
classe: "note"+(($scope.tasks.length%3)+1),
steps: [],
});
TasksService.addStepGroup();
}
$scope.addGroup = function(title, description, color) {
$scope.newgroup = false;
var image = "";
if(color === "red") {
image = "pin3.png";
} else if (color === "yellow") {
image = "pin.png";
} else if (color === "green") {
image = "pin4.png";
} else if (color === "blue") {
image = "pin2.png";
}
TasksService.addGroup({
name: title,
description: description,
color: color,
image: image,
});
}
this.addStep = function(title, body) {
TasksService.addStep({
id: $scope.tasks[$scope.id].steps.length || 0,
title: title,
body: body,
status: "notyet",
}, $scope.id);
}
});
why doesn't work the second one?
the error is: Uncaught ReferenceError: drag is not defined... why?

Categories