I have this problem with integrating paper.js into angular.js. My issue is that I simply doesn't know where to load the paperscript part.
I have a view and a controller and I can't really place the code in the controller for what I know and it wont load if it is placed in the view.
My controller look like this:
var hash = window.location.hash.split('/');
$scope.status = 'Loading';
var request = jQuery.ajax(system.server, {
'url': system.server,
'headers': {
'Accept': 'application/json',
'Request': system.request + '/hcbs/allocations/resident/' + hash[3],
'Username': system.username,
'Password': system.password
}
})
.always(function(response)
{
signature.constructor();
switch(response.status)
{
case 200:
case undefined:
$scope.$apply(function()
{
$scope.status = '';
var res = JSON.parse(response);
$scope.hcbsAllocations = res.hcbsServiceAllocations;
$scope.change = function(allocationId)
{
console.log(jQuery('[data='+ allocationId +'][name=startDate]').val());
console.log(jQuery('[data='+ allocationId +'][name=endDate]').val());
}
$scope.submit = function(allocationId)
{
// Validate dates
// Make signature popup
$scope.signaturePop = true;
}
});
break;
case 404:
console.log('error ' + response.status);
$scope.$apply(function()
{
$scope.status = 'Problems loading ressource at the moment';
});
default:
console.log(response);
}
});
My view looks like this:
<div id="app-content">
<div consumer />
<h1>Consumer</h1>
<div ng-show="status">
<div class="notice">
<p>{{status}}</p>
</div>
</div>
<form name="attendance">
<table class="hcbs">
<tr ng-repeat="allocation in hcbsAllocations">
<td class="first"><h3>{{allocation.type}}</h3></td>
<td class="middle">
<input type="datetime-local" name="startDate" ng-model="startDate" ng-change="change(allocation.id)" data="{{allocation.id}}" placeholder="Choose start date" />
<input type="datetime-local" name="endDate" ng-model="endDate" ng-change="change(allocation.id)" data="{{allocation.id}}" placeholder="Choose end date" />
</td>
<td class="last">
<span class="btn" class="submit" data="{{allocation.id}}" ng-click="submit(allocation.id)"><i class="icon-ok icon-large"></i></span>
</td>
</tr>
</table>
</form>
</div>
The directive approach to this:
Check out the jsFiddle
HTML:
<canvas id="canvas" resize draw></canvas>
directive:
app.directive('draw', function () {
return {
restrict: 'A',
link: function postLink(scope, element, attrs) {
var path;
var drag = false;
function mouseUp(event) {
//Clear Mouse Drag Flag
drag = false;
}
function mouseDrag(event) {
if (drag) {
path.add(new paper.Point(event.layerX, event.layerY));
path.smooth();
}
}
function mouseDown(event) {
//Set flag to detect mouse drag
drag = true;
path = new paper.Path();
path.strokeColor = 'black';
path.add(new paper.Point(event.layerX, event.layerY));
}
function initPaper() {
paper.install(window);
paper.setup('canvas');
}
element.on('mousedown', mouseDown).on('mouseup', mouseUp).on('mousemove', mouseDrag);
initPaper();
}
};
});
There is no need to load paperscript. You can use javascript directly
<body ng-controller="PaperController">
<canvas id="canvas" resize ng-mousedown="mouseDown($event)" ng-mousemove="mouseDrag($event)" ng-mouseup="mouseUp()"></canvas>
</body>
<script type="text/javascript">
function PaperController($scope){
var path;
var drag = false;
$scope.mouseUp = function(){
//Clear Mouse Drag Flag
drag = false;
};
$scope.mouseDrag = function(event){
if(drag){
path.add(new paper.Point(event.x, event.y));
path.smooth();
}
};
$scope.mouseDown = function(event){
//Set flag to detect mouse drag
drag = true;
path = new paper.Path();
path.strokeColor = 'black';
path.add(new paper.Point(event.x, event.y));
};
init();
function init(){
paper.install(window);
paper.setup('canvas');
}
}
</script>
The previous solutions doesn't work for me, and they are also with a lot of redundant code and IDs.
jsFiddle
I just have my element, suppose
<canvas draw></canvas>
And a simple directive like this one:
app.directive('draw', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var path;
paper.setup(element.get(0));
var tool = new paper.Tool();
tool.onMouseDown = function (event) {
path = new paper.Path();
path.strokeColor = 'black';
};
tool.onMouseDrag = function (event) {
path.add(event.point);
};
tool.onMouseUp = function (event) {
//nothing special here
};
}
};
});
Related
This is a difficult question to ask, I will do my best to be brief:
I have a simple controller that I want to use to get information from an API and populate a selection list from trello.
Here is my controller:
function TrelloController($scope, $location, $routeParams, $timeout, dialogs, common){
var vm = this;
var controllerId = 'TrelloController';
var getLogFn = common.logger.getLogFn;
var log = getLogFn(controllerId);
var logError = getLogFn(controllerId, 'error');
var scope = $scope;
var TRELLO = require("trello");
var key = '<my key>';
var token = '<my token>';
var trello = new TRELLO(key, token);
vm.title = "Trello Controller";
vm.addCard = addCard;
vm.getBoards = getBoards;
vm.toggle = toggle;
vm.getLists = getLists;
vm.getListsFromDictionary = getListsFromDictionary;
vm.isTrelloActive = false;
activate();
function activate(){
common.activateController([], controllerId)
.then(function () {
log('Activated Trello Controller');
initialise();
});
}
function initialise() {
vm.isTrelloActive = false;
getBoards();
getLists();
}
function toggle() {
vm.isTrelloActive = !vm.isTrelloActive;
log("TOGGLE CLICKED");
}
function addCard(cardName, cardDescription, listId) {
trello.addCard(cardName, cardDescription, listId, function (error, cardAdded) {
if (error) {
log("Could Not Add Card: ", error);
} else {
log("Card added: ", cardAdded.name);
}
});
}
function getBoards() {
trello.getBoards("me", function (error, boards) {
if (error) {
log("Could Not Get Boards: ", error);
} else {
log("found " + boards.length + " boards");
console.log(boards);
}
scope.boards = boards;
});
}
function getLists(){
for (var i=0; i<scope.boards.length; i++){
getListsWithBoardId(scope.boards[i].id, i);
}
}
function getListsWithBoardId(boardId, index){
trello.getListsOnBoard(boardId, function(error, lists){
if (error) {
log("Could Not Get Boards: ", error);
} else {
log("found " + lists.length + " lists on board:"+boardId);
console.log(lists);
}
scope.boards[index].lists = lists;
});
}
function getListsFromDictionary(boardId){
for (var i=0; i<scope.boards.length; i++) {
if(scope.boards[i].id == boardId){
return scope.boards[i].lists;
}
}
}
}module.exports = TrelloController;
This controller is intended to serve the purpose of governing my dialogue, simplified, this is that dialogue:
<div data-ng-controller="TrelloController as vm">
<div class="modal-header">
<img class="trelloLogo" name="trelloLogo" src="public/content/images/trello-mark-blue.png" alt="Add To Trello" ng-click="vm.toggle}">
<h3>{{parameter.heading}}</h3>
</div>
<div class="modal-body">
<form name="form">
<div ng-if="vm.isTrelloActive" class="form-group">
<label>Board</label>
<select name="typeInput" class="form-control" ng-required="true" ng-model="form.boardInput">
<option selected>Choose Board</option>
<option ng-repeat="board in scope.boards" value="{{board.id}}">{{board.name}}</option>
</select>
</div>
</form>
</div>
<!-- This section contains parts in the vm.addCard(...) that aren't included in this shortened version of The HTML template, I provided it with the additional fields for context of the API call at the end -->
<div ng-if="vm.isTrelloActive" class="modal-footer">
<button class="btn btn-primary" ng-disabled="!form.$dirty || !form.$valid" ng-click="vm.addCard(form.titleInput, form.descriptionInput, form.listInput)">Add To Board</button>
<button class="btn btn-default" ng-click="vm.isTrelloActive=false">Cancel</button>
</div>
</div>
When I am in the dialogue, Pressing the logo button appears to do nothing even though when it was previously set to: ng-click="vm.isTrelloActive = !vm.isTrelloActive" it would toggle the entire page. The activate method produces no logs and does not appear to run when pressed.
Why is this happening?
I have a simple post that gets my json objects.
Inside my json I have 2 or more campaigns, campaigns is a array.
within a campaign array I have slots, slots is a array that has 1 or more base_image within.
I display on screen for each campaign.
max_slots
c_name
slots.base_image
so that I can show each campaign name, maximum slots allowed and the images associated within each campaign.
AIM
I am trying to have a upload image and preview image for each campaign so you only see the image preview to the campaign your uploading it to.
PROBLEM
At the moment I upload a image and it shows on the preview for all campaigns, not the individual campaign.
See image bellow:
HTML
<body ng-app="myApp">
<div ng-controller="Dashboard">
<!--FIRST ng-repeat-->
<div ng-repeat="campaign in campaigns" class="campaign-container">
<div class="container">
<h1>{{campaign.c_name}} {{$index}}</h1>
<strong>This Campaign you are allowed {{campaign.max_slots}} Images</strong>
<table class="table">
<thead>
<tr>
<th>Select File</th>
<th>Preview Image</th>
<th>Add to list</th>
<th>Images</th>
<!--<th>Remove Image</th>-->
<th>Save Campaign</th>
</tr>
</thead>
<tbody>
<tr>
<td> <!--UPLOAD IMAGE-->
<div class="upload-new">
<input id="fileinput" ng-model="file" type="file" ng-model-instant="" name="file"
accept="image/*"
onchange="angular.element(this).scope().uploadImage(this)">
</div>
<!--END-->
</td>
<td> <!--PREVIEW IMAGE-->
<div class="preview">
<img style="height: 100px; width: 100px" ng-src="{{preview}}" alt="preview image">
</div>
<!--END--></td>
<td>
<button ng-click="addImage()">Add image</button>
</td>
<td>
<div ng-repeat="slot in campaign.slots" class="slot">
<img ng-click="addImage()" style="height: 100px; width: 100px" ng-src="{{base_image}}"
alt="slot image">
<button ng-click="removeImage(slot)">Remove Image</button>
</div>
</td>
<!--<td>Remove button to be here</td>-->
<td>
<button ng-click="SaveImage()">Save to API</button>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--END FIRST ng-repeat-->
</div>
</body>
JavaScript
.controller('Dashboard', function ($scope, $http, $timeout) {
$scope.campaigns = [];
$scope.preview = '';
// $scope.slots = [];
$scope.maxSlots = [5];// this dynamic
$scope.uploadImage = function () {
// console.log('we are here');
input = document.getElementById('fileinput');
file = input.files[0];
size = file.size;
if (size < 650000) {
var fr = new FileReader;
fr.onload = function (e) {
var img = new Image;
img.onload = function () {
var width = img.width;
var height = img.height;
if (width == 1920 && height == 1080) {
$scope.preview = e.target.result;
$scope.perfect = "you added a image";
$scope.$apply();
} else {
$scope.notPerfect = "incorrect definitions";
}
};
img.src = fr.result;
};
fr.readAsDataURL(file);
} else {
$scope.notPerfect = "to big";
}
};
$scope.addImage = function (index) {
if ($scope.campaigns[index].slots.length < $scope.campaigns.maxSlots) {
$scope.campaigns[index].slots.push({
"slot_id": $scope.campaigns[index].slots.length + 1,
"base_image": $scope.preview,
"path_image": ""
});
} else {
window.alert("you have to delete a slot to generate a new one");
}
};
$scope.GetData = function () {
$http({
url: "http://www.site.co.uk/ccuploader/campaigns/getCampaign",
method: "POST",
date: {},
headers: {'Content-Type': 'application/json'}
}).then(function (response) {
// success
console.log('you have received the data ');
// console.log(response);
$scope.campaigns = response.data;
console.log("logging campaings", $scope.campaigns);
//$scope.slots = response.data[0].slots;
//$scope.maxSlots = response.data[0].maxSlots;
}, function (response) {
// failed
console.log('failed getting campaigns goo back to log in page.');
// console.log(response);
});
};
$scope.GetData();
})
You have only one preview variable in your controller, but you need one per campaign. You may want to pass the index of the campaign into your uploadImage function.
I'm not sure if the way you're doing file inputs is correct (haven't done it much myself), but you need something like this:
Template:
<input type="file" onchange="angular.element(this).scope().uploadImage(this, $index)">
<img ng-src="{{campaign.preview}}" alt="preview image">
Controller:
$scope.uploadImage = function (element, index) {
// Remove this - there are many file inputs with this ID. Use the element or index arguments?
// input = document.getElementById('fileinput');
// ...
if (width == 1920 && height == 1080) {
$scope.campaigns[index].preview = e.target.result;
}
}
As mentioned in my comment above, you were also calling input = document.getElementById('fileinput'); to get the file input, but ng-repeat will have created many inputs with that ID. Maybe you should use the input or index that is passed into uploadImage(this, $index). If for some reason you still need to use getElementById instead of using the element you passed in, you could generate unique ID's using the index:
<input id="fileinput-{{ $index }}"
Edit: The OP used the answer above with a few modifications:
HTML
<input id="fileinput-{{ $index }}" ng-model="file" type="file" ng-model-instant="" name="file" accept="image/*" onchange="angular.element(this).scope().uploadImage(this)">
Controller
$scope.uploadImage = function (element, index) {
console.log(element);
console.log(element.id);
str = element.id;
str = str.substr(str.indexOf('-') + 1);
console.log(str);
index = str;
// console.log('we are here');
input = element;
file = input.files[0];
size = file.size;
if (size < 650000) {
var fr = new FileReader;
fr.onload = function (e) {
var img = new Image;
img.onload = function () {
var width = img.width;
var height = img.height;
if (width == 1920 && height == 1080) {
console.log('we are here');
$scope.campaigns[index].preview = e.target.result;
// $scope.preview = e.target.result;
$scope.perfect = "you added a image";
$scope.$apply();
} else {
$scope.notPerfect = "incorrect definitions";
}
};
img.src = fr.result;
};
fr.readAsDataURL(file);
} else {
$scope.notPerfect = "to big";
}
};
How can I apply confirm dialog box in below button in angularjs ?
<button class="btn btn-sm btn-danger" ng-click="removeUser($index)">Delete</button>
Just like this.
<span><a class="button" onclick="return confirm('Are you sure to delete this record ?')" href="delete/{{ item.id }}">Delete</span>
Update
Currently I am doing it like this
function removeUser(index) {
var isConfirmed = confirm("Are you sure to delete this record ?");
if(isConfirmed){
vm.users.splice(index, 1);
}else{
return false;
}
};
Here is the snippets,
how your HTML should be,
<button class="btn btn-sm btn-danger" ng-confirm-click="Are you sure to delete this record ?" confirmed-click="removeUser($index)">Delete</button>
Please Include this directive in your custom angularjs file,
app.directive('ngConfirmClick', [
function(){
return {
link: function (scope, element, attr) {
var msg = attr.ngConfirmClick || "Are you sure?";
var clickAction = attr.confirmedClick;
element.bind('click',function (event) {
if ( window.confirm(msg) ) {
scope.$eval(clickAction)
}
});
}
};
}])
Your angular scope based on your delete function mentioned above,
$scope.removeUser = function(index) {
vm.users.splice(index, 1);
}
$scope.removeUser= function (ind){
if (confirm("Are you sure?")) {
alert("deleted"+ s);
$window.location.href = 'delete/'+ s;
}
}
http://jsfiddle.net/ms403Ly8/61/
I would separate the message bit from the delete action bit, that way you could reuse the confirm bit in other parts of your app:
I use a directive like so:
angular.module('myModule').directive("ngConfirmClick", [
function() {
return {
priority: -1,
restrict: "A",
link: function(scope, element, attrs) {
element.bind("click", function(e) {
var message;
message = attrs.ngConfirmClick;
if (message && !confirm(message)) {
e.stopImmediatePropagation();
e.preventDefault();
}
});
}
};
}
]);
then have your controller function with the delete action:
$scope.removeUser(index) {
//do stuff
}
and in the View I would use ng-click:
<span><a class="button" ng-confirm-click="Are you sure?" ng-click="removeUser(item.id}}">Delete</span>
hope it helps.
You can try this plunker: http://plnkr.co/edit/xJJFxjYeeHmDixAYPu4c?p=preview
You can create a directive for the dialog.
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $window) {
$scope.delete = function(id) {
$window.location.href = 'delete/'+ id;
}
});
app.directive('ngConfirmClick', [
function(){
return {
link: function (scope, element, attr) {
var msg = attr.ngConfirmClick || "Are you sure?";
var clickAction = attr.confirmedClick;
element.bind('click',function (event) {
if ( window.confirm(msg) ) {
scope.$eval(clickAction)
}
});
}
};
}])
Here i am using angular service.In my case i am getting value for first app but not for second .please help me .
thank you.
here is my html:-
<div ng-app="mainApp" ng-controller="CalcController">
<p>Enter a number: <input type="number" ng-model="number" />
<button ng-click="multiply()">X<sup>2</sup></button>
<p>Result: {{result}}</p>
</div>
<div ng-app="myApp2" ng-controller="myController2">
<p>Enter a number: <input type="number" ng-model="numberSecond" />
<button ng-click="multiplyValue()">X<sup>2</sup></button>
<p>Result: {{result2}}</p>
</div>
here is js:-
angular.module('myReuseableMod',[]).factory('$myReuseableSrvc',function()
{
// code here
var factory = {};
factory.multiply = function(a)
{
return a * a
}
return factory;
});
var mainApp = angular.module("mainApp", ['myReuseableMod']);
mainApp.controller('CalcController',['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
alert("inside controller");
$scope.multiply = function()
{
alert("hello1");
$scope.result = $myReuseableSrvc.multiply($scope.number);
}
}]);
var mainApp2 = angular.module("myApp2", ['myReuseableMod']);
mainApp.controller('myController2',['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
alert("inside controller");
$scope.multiplyValue = function()
{
alert("hello1");
$scope.result2 = $myReuseableSrvc.multiply($scope.numberSecond);
}
}]);
Your 'myController2' is in the wrong app
mainApp.controller('myController2'
Should be:
mainApp2.controller('myController2'
EDIT:
Ah yes I see the problem. You cannot use ng-app twice like that. If you want what you are trying to achieve which is multiple applications you have to 'bootstrap' the second one:
plunk here:
http://plnkr.co/edit/qfllLO9uy6bC5OLkHnYZ?p=preview
angular.module('myReuseableMod',[]).factory('$myReuseableSrvc',function() {
var factory = {};
factory.multiply = function(a) {
return a * a
}
return factory;
});
var mainApp = angular.module("mainApp", ["myReuseableMod"]);
mainApp.controller('CalcController', ['$scope', '$myReuseableSrvc',function($scope, $myReuseableSrvc) {
$scope.multiply = function() {
$scope.result = $myReuseableSrvc.multiply($scope.number);
}
}]);
var mainApp2 = angular.module("mainApp2", []);
mainApp2.controller("MyController2", function($scope, $myReuseableSrvc) {
console.log('init B');
$scope.multiplyValue = function() {
$scope.result2 = $myReuseableSrvc.multiply($scope.numberSecond);
}
});
angular.element(document).ready(function() {
angular.bootstrap(document.getElementById("myDiv2"), ["mainApp2", "myReuseableMod"]);
});
This is a good post to read:
http://www.simplygoodcode.com/2014/04/angularjs-getting-around-ngapp-limitations-with-ngmodule/
In my model, I have a field that I need several controls to bind to. One of these controls is a text box. The text box should not directly edit the field, but instead it should allow the user to type and then either commit the changes or cancel. If any other operation occurs then it should overwrite any changes in the text field. One constraint is that there are other UI components that change the value and do not have access to the local scope.
I implemented the desired behavior with a directive: http://jsfiddle.net/fLxjjmb7/3/
It works as intended, but I feel that there must be a better way to do this. Any ideas?
<div ng-app="app" ng-controller="controller">
<div>{{foo}}</div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
<br />
<div shadow="foo">
<input type="text" ng-model="foo" />
<button ng-click="commit()">update</button>
<button ng-click="cancel()">cancel</button>
</div>
</div>
var app = angular.module('app', []);
var controller = app.controller('controller', function ($scope) {
$scope.foo = 1;
$scope.increment = function () { ++$scope.foo; };
$scope.decrement = function () { --$scope.foo; };
});
var directive = app.directive('shadow', function() {
return {
scope: true,
link: function(scope, el, att) {
scope.$parent.$watch(att.shadow, function (newValue) {
scope[att.shadow] = newValue;
});
scope.commit = function() {
scope.$parent[att.shadow] = angular.copy(scope[att.shadow]);
};
scope.cancel = function() {
scope[att.shadow] = angular.copy(scope.$parent[att.shadow]);
};
}
};
});
Think you are complicating this a bit :)
View:
<div ng-controller="ShadowController">
<h1>{{foo}}</h1>
<div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
</div>
<div>
<input type="text" ng-model="tempFoo" />
<button ng-click="commit()">update</button>
<button ng-click="cancel()">cancel</button>
</div>
</div>
Controller:
.controller('ShadowController', function ($scope) {
$scope.foo = 1;
$scope.increment = function () {
++$scope.foo;
$scope.cancel();
};
$scope.decrement = function () {
--$scope.foo;
$scope.cancel();
};
$scope.commit = function () {
$scope.foo = parseFloat($scope.tempFoo);
};
$scope.cancel = function () {
$scope.tempFoo = $scope.foo;
};
$scope.cancel();
});
An even fancier way would be to keep track of changes to the temporary value and only enable commit/cancel buttons if there is a diff between original and temp.
View:
<div ng-controller="ShadowControllerAdv">
<h1>{{data.original}}</h1>
<div>
<button ng-click="increment()">increment</button>
<button ng-click="decrement()">decrement</button>
</div>
<div>
<input type="text" ng-model="data.edit" />
<button ng-click="commit()" ng-disabled="!state.hasChanged">update</button>
<button ng-click="reset()" ng-disabled="!state.hasChanged">cancel</button>
</div>
</div>
Controller:
.controller('ShadowControllerAdv', function ($scope) {
var _dataWatcher;
$scope.data = {
original: 1
};
$scope.state = {
hasChanged: false
};
function _startWatcher() {
_dataWatcher = $scope.$watch('data.edit', function (newValue, oldValue) {
if (newValue !== oldValue) {
$scope.state.hasChanged = true;
} else {
$scope.state.hasChanged = false;
}
}, true);
}
function _stopWatcher() {
if (!_dataWatcher) {
return;
}
_dataWatcher();
}
$scope.reset = function () {
_stopWatcher();
$scope.data.edit = $scope.data.original;
$scope.state.hasChanged = false;
_startWatcher();
}
$scope.commit = function () {
_stopWatcher();
$scope.data.original = parseFloat($scope.data.edit);
$scope.reset();
}
$scope.increment = function () {
$scope.data.original = $scope.data.original + 1;
$scope.reset();
};
$scope.decrement = function () {
$scope.data.original = $scope.data.original - 1;
$scope.reset();
};
$scope.reset();
});