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?
Related
I am facing an issue while using mdDialog confirm from angularJS material design. I am using the confirm box to ask a user for his choice to continue or confirm, If the user confirms the API will take the value and return the returns or else return, however my API is still being called even if the user does not confirm anything. I was able to get around the issue by using normal confirm and alert box but would be thankful if some body can suggest me a fix. I have looked into promises but could not figure how to implement it in my code. Here is a snippet of my code
if ($scope.options.selected[i].field === "displayInterval") {
data.aggregations = "date:" + $scope.options.selected[i].value.toString();
if (data.aggregations === 'date:hour' || 'date:minute') {
var confirm = $mdDialog.confirm()
.title('Some of the providers you selected do not support this display interval.')
.textContent('Continue with only sources that support by hour or minute charting.')
.ok('Yes')
.cancel('No');
$mdDialog.show(confirm).then(function() {
$scope.aggs = data.aggregations;
}, function() {
return;
});
} else {
$scope.aggs = data.aggregations;
}
}
rts.doSearch(data).then(function(response){
$('.lineChart').show();
if (response.status == 500 || response.status == 404 || response.status == 401) {
alert("Error:" + response.message);
return;
}
loadAggregation(response.provider_results, data.query);
So here rts.doSearch(data) is the call being made to the API which is getting executed regardless of the if condition before it.
I use something similar but it's ui instead of Material, anyway i believe it could give the clues to make it work.
app.controller('prioridade', function($scope, $filter, $uibModal) {
$scope.prioridades = response.data;
$scope.mymodal={};
$scope.openmymodal = function(msize, mtimeout, mbackdrop, mclass, mresponse){ /*this has some variables to make it dynamic*/
$scope.mymodal.size = msize!=''?msize:'md';
$scope.mymodal.timeout = mtimeout!=''?mtimeout:0;
$scope.mymodal.backdrop = mbackdrop!=''?mbackdrop:true;
$scope.mymodal.mclass = mclass!=''?mclass:'btn-success';
$scope.mymodal.mresponse = mresponse!=''?mresponse:'no';/*aguardar por resposta yes or no*/
var modalInstance = $uibModal.open({
animation: true, ariaLabelledBy: 'modal-title', ariaDescribedBy: 'modal-body',
templateUrl: 'myMainModal.html', controller: 'ModalInstanceCtrl', keyboard: true,
controllerAs: '$ctrl', size: $scope.mymodal.size, backdrop: $scope.mymodal.backdrop,/*true or 'static'*/
resolve: {mymodal: function(){return $scope.mymodal;}} /*to pass the variables to the modal*/
});
modalInstance.result.then(function(result) {
$scope.myresult = result;
if($scope.myresult.results=='OK'){
/*do what ever you want*/
} else { /*if canceled*/}
});
};
/*here is where i call the modal function*/
$scope.resetPSW = function(user) {
$scope.mymodal.header='! Atenção está prestes a Apagar a Psw do User!';
$scope.mymodal.body='<div class="col-md-12 col-sm-12 col-xs-12">** Tem a certeza que pretende apagar a Psw deste user? **</div>';
$scope.mymodal.post=user; $scope.openmymodal('md', 1, true, 'btn-danger', 'yes');
};
});
app.controller('ModalInstanceCtrl', function ($uibModalInstance, mymodal, $timeout, $sce) {
var $ctrl = this; $ctrl.mymodal = mymodal; $ctrl.mymodal.body = $sce.trustAsHtml($ctrl.mymodal.body);
switch($ctrl.mymodal.timeout){
case 0, 1:
$ctrl.ok = function(){$ctrl.mymodal['results'] = 'OK'; $uibModalInstance.close($ctrl.mymodal);};
$ctrl.cancel = function(){$uibModalInstance.dismiss('cancel');};
break;
default:
promise = $timeout(function(){$uibModalInstance.dismiss('cancel');}, 3000);
$ctrl.ok = function(){$ctrl.mymodal['results'] = 'OK'; $timeout.cancel(promise); $uibModalInstance.close($ctrl.mymodal);};
$ctrl.cancel = function(){$timeout.cancel(promise); $uibModalInstance.dismiss('cancel');};
break;
};
});
and the HTML
<script type="text/ng-template" id="myMainModal.html">
<div class="modal-header" ng-class="$ctrl.mymodal.mclass">
<h3 class="modal-title" id="modaltitle">{{$ctrl.mymodal.header}}</h3>
</div>
<div class="modal-body" id="modalbody" ng-bind-html="$ctrl.mymodal.body"></div>
</br>
<div class="modal-footer" id="modalfooter" ng-show="$ctrl.mymodal.timeout<=2">
<button class="btn btn-primary" type="button" ng-click="$ctrl.ok()">OK</button>
<button class="btn btn-warning" type="button" ng-click="$ctrl.cancel()" ng-show="$ctrl.mymodal.timeout==1">Cancel</button>
</div>
</script>
I am trying to create Just the way Facebook Post gets display. Here Conversation Message Contains the list of Post and on-click of the Post get-comments is getting Called which will fetch all the Comments as well as Reply corresponding to that Comment.
<div ng-repeat="coversationMessage in coversationMessageList">
<div ng-click="getComments(coversationMessage.channel_message_ID)">
<div>{{coversationMessage.date_time}}</div>
<div>{{coversationMessage.channel_message}}</div>
<div ng-if='commentList.length!=0'>
<div ng-repeat="comment in commentList">
<div>{{comment.date_time}}</div>
<div><b>{{comment.channel_message}}</b></div>
<div ng-if="commentMsg.replyCount> 0">
<div><a ng-click="showhideReply($index+1);$event.stopPropagation()">{{commentMsg.replyCount}}Replies</a></div>
<div class="mailText" ng-repeat="replyMessage in commentMsg.replyList">
<div>{{replyMessage.date_time |formatDateTime}}</div>
<div>{{replyMessage.channel_message}}</div>
</div>
</div>
</div>
</div>
</div>
Get Post Method will Populate the coversationMessageList (Array)
$scope.getPost = function(channel_thread_id) {
var promise = dashboardServices.getConversation(channel_thread_id);
promise.then(function(data) {
$scope.coversationMessageList = data.data;
}).catch(function(error) {
console.log("Error in fetching Conversation " + error);
});
}
Get Comments Will Populate commentList, replyCount and replyList
$scope.getComments = function(channel_thread_id) {
var promise = dashboardServices.getConversation(channel_thread_id);
promise.then(function(data) {
$scope.commentList = data.data;
console.log(JSON.stringify(data.data));
// This foreach method is to show comment reply for facebook
angular.forEach($scope.commentList, function(comment) {
if (comment.channel_message_ID) {
var channel_thread_id = comment.channel_message_ID;
var promise = dashboardServices.countReplyOnComment(channel_thread_id);
promise.then(function(data) {
$scope.commentMsg = {};
$scope.commentMsg = comment;
$scope.commentMsg.replyCount = {};
$scope.commentMsg.replyList = {};
$scope.countReply = data.data.length;
$scope.commentMsg.replyCount = $scope.countReply;
$scope.commentMsg.replyList = data.data;
comment = $scope.commentMsg;
console.log(comment);
}).catch(function(error) {
});
}
});
}).catch(function(error) {
});
}
The Problem is when i click on a Particular div the Comments and the reply is getting reflected to all the other div
Move the commentList into coversationMessage ...
Try the below code :
<div ng-repeat="coversationMessage in coversationMessageList">
<div ng-click="getComments(coversationMessage)">
<div>{{coversationMessage.date_time}}</div>
<div>{{coversationMessage.channel_message}}</div>
<div ng-if='coversationMessage.commentList && coversationMessage.commentList.length!=0'>
<div ng-repeat="comment in coversationMessage.commentList">
<div>{{comment.date_time}}</div>
<div><b>{{comment.channel_message}}</b></div>
<div ng-if="commentMsg.replyCount> 0">
<div><a ng-click="showhideReply($index+1);$event.stopPropagation()">{{commentMsg.replyCount}}Replies</a></div>
<div class="mailText" ng-repeat="replyMessage in commentMsg.replyList">
<div>{{replyMessage.date_time |formatDateTime}}</div>
<div>{{replyMessage.channel_message}}</div>
</div>
</div>
</div>
</div>
</div>
The service :
$scope.getComments = function (coversationMessage) {
var channel_thread_id = coversationMessage.channel_message_ID;
var promise = dashboardServices.getConversation(channel_thread_id);
promise.then(function (data) {
coversationMessage.commentList = data.data;
console.log(JSON.stringify(data.data));
// This foreach method is to show comment reply for facebook
angular.forEach(coversationMessage.commentList, function (comment) {
if (comment.channel_message_ID) {
var channel_thread_id = comment.channel_message_ID;
var promise = dashboardServices.countReplyOnComment(channel_thread_id);
promise.then(function (data) {
$scope.commentMsg = {};
$scope.commentMsg = comment;
$scope.commentMsg.replyCount = {};
$scope.commentMsg.replyList = {};
$scope.countReply = data.data.length;
$scope.commentMsg.replyCount = $scope.countReply;
$scope.commentMsg.replyList = data.data;
comment = $scope.commentMsg;
console.log(comment);
}).catch(function (error) {
});
}
});
}).catch(function (error) {
});
}
I want to update a variable called hideProgressBar the Directive "ng-hide" in this view through the $ scope in my control. But it does not work.
The line below works:
$ Scope.hideProgessBar = true;
But the line below does not work:
$ Scope.hideProgessBar = false;
see the complete code below:
.controller('UltimasEdicoesCtrl', function($scope, $cordovaFileTransfer, $cordovaFileOpener2) {
$scope.hideProgessBar = true;
$scope.Download = function () {
$scope.hideProgessBar = false;
ionic.Platform.ready(function($scope){
var url = "http://www.wgontijo.com.br/teste.pdf";
var filename = url.split("/").pop();
var targetPath = cordova.file.externalRootDirectory + 'Pictures/' + filename;
$cordovaFileTransfer.download(url, targetPath, {}, true).then(function (result) {
$cordovaFileOpener2.open(
targetPath,
'application/pdf'
).then(function() {
// file opened successfully
}, function(err) {
alert('erro ao abrir o arquivo')
});
}, function (error) {
alert('Erro ao abrir o arquivo');
}, function (progress) {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
});
});
}
})
HTML
<div class="w3-progress-container" ng-hide="{{hideProgessBar}}">
<div id="myBar" class="w3-progressbar w3-green" style="width:{{downloadProgress}}%">
<div id="demo" class="w3-center w3-text-white">{{downloadProgress}}%</div>
</div>
</div>
You need to just remove the braces {{}} from ng-hide="{{hideProgessBar}}" and everything will work. The reason it doesn't work with the curly braces because the ng-hide directive is already looking for Angular attributes, so that will not tell Angular to that there is variable.
Try this:
<div class="w3-progress-container" ng-hide="hideProgessBar">
<div id="myBar" class="w3-progressbar w3-green" ng-style="{ width: downloadProgress + '%' }">
<div id="demo" class="w3-center w3-text-white">{{downloadProgress}}%</div>
</div>
</div>
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();
});
I'm having some issues with the flow of my application. I'm trying to refresh a list when a new item has been created using a modal.
This is what the logic should be:
Hit new group button Modal shows up,
fill form Submit form, data is sent over to the service
Service creates the new group and calls the getGroup()
getGroups retrieves the new list of groups, the service resolves
After the service is done I need to set variables in my main ctrl so the DOM reflects the new change
HTML:
<div class="topPanel">
<div class="topRow">
<label for="entityDropDown">Select a Group:</label>
<select id="entityDropDown" ng-model="selectedGroup" ng-options="group as group.name for group in groups" ng-change="getGroupInfo(selectedGroup)"></select>
<button type="button" class="delGroupBtn btn-danger" ng-disabled="!selectedGroup" ng-click="deleteGroup()">✖</button>
<button type="button" class="delGroupBtn btn-success" ng-click="newGroup()">New Group</button>
</div>
<div class="userGroups" ng-show="selectedGroup">
<div>
<label for="entityAvailable">Available Users</label>
<select id="entityAvailable" multiple ng-model="selectedAvailableUsers" ng-options="u.name for u in availableUsers | orderBy: 'name'"></select>
</div>
<div id="moveButtons">
<button type="button" ng-disabled="!selectedGroup || availableUsers.length === 0 || selectedAvailableUsers.length === 0" ng-click="manageGroup(true)">Add to Group</button>
<button type="button" ng-disabled="!selectedGroup || assignedUsers.length == 0 || selectedAssignedUsers.length === 0" ng-click="manageGroup(false)">Remove from Group</button>
</div>
<div>
<label for="entityAssigned">Users In Group</label>
<select id="entityAssigned" multiple ng-model="selectedAssignedUsers" ng-options="u.name for u in assignedUsers | orderBy:'name'"></select>
</div>
</div>
<br class="clearfix" />
</div>
groupCtrl:
$scope.newGroup = function (){
var d = $q.defer();
var modalForm = '/Style%20Library/projects/spDash/app/partials/newGroup.html';
var modalInstance = $modal.open({
templateUrl: modalForm,
backdrop: true,
windowClass: 'modal',
controller: newGroupCtrl,
resolve:{
newGroup:function (){
return $scope.newGroup;
}
}
});
$scope.selectedGroup = false;
$scope.groups = groupService.getGroups();
d.resolve();
return d.promise;
};
/*At first I wanted to set newGroups to return a promise and then manipulate the $scope elements.But I got error then() is not a function of $scope.newGroup so I had to move the scope elements up into the function but now it runs before the service is even done. */
/*$scope.newGroup.then(function(){
$scope.selectedGroup = false;
$scope.groups = groupService.getGroups();
},
function(){
console.log('failed to create new group');
});*/
Modal newGroupCtrl:
var newGroupCtrl = function ($scope, $modalInstance, groupService){
$scope.newGroup = {};
$scope.submit = function(){
console.log('creating new group');
console.log($scope.newGroup);
$modalInstance.close($scope.newGroup);
}
$scope.cancel = function (){
$modalInstance.dismiss('Cancelled group creation');
};
$modalInstance.result.then(function (newGroup){
groupService.createGroup(newGroup);
}, function (reason){
console.log(reason);
});
}
createGroup Service function:
var createGroup = function (newGroup) {
var deferred = $q.defer();
var currentUser = $().SPServices.SPGetCurrentUser({
fieldName: "Name",
debug: false
});
var promise = $().SPServices({
operation: "AddGroup",
groupName: newGroup.name,
description: newGroup.desc,
ownerIdentifier: currentUser,
ownerType: "user",
defaultUserLoginName: currentUser,
})
promise.then(function (){
console.log('new group created');
getGroups();
deferred.resolve();
},
function(){
console.log('failed to create new group');
deferred.reject();
});
return deferred.promise;
}
Problem: How do I get the main controller to run functionsAFTER the createGroup service function has finished and returned it's promise?
For example, once the modal calls createGroup service function and that function updates my user list, I need to set these elements in the main groupCtrl:
$scope.selectedGroup = false;
$scope.groups = groupService.getGroups();