I want to make chat app. So when I send message you can hear pop. So i have two directives, one for my messages and other for simulation. Simulation is working just one time and then stop. I cant get objects from $scope.data to directive myDirective. I really tried almost everything. Is there any solution?
var app = angular.module('myApp', ['ui.router']);
app.config(function($stateProvider, $urlRouterProvider,$locationProvider) {
//angular-ui-router
$urlRouterProvider.otherwise('/');
$stateProvider
.state('home',{
url:'/',
views:{
'':{
templateUrl:'../ChatApp/views/chatapp.html'
}
}
})
.state('login',{
url:'/login',
templateUrl:'../ChatApp/views/login.html',
controller: 'LoginController'
});
});
app.controller('MessageController', function($scope,$filter, $http,$state,$timeout,$compile,$interval) {
$scope.randomNumber = Math.floor(Math.random()*(2-0+1)+0);
$scope.data = [];
$scope.name = localStorage.getItem('Name');
console.log(localStorage);
console.log(localStorage.getItem('Name'));
$scope.sendedMessage = "";
$scope.data1 = [$scope.name,$scope.sendedMessage,$scope.date];
//geting data from json
$scope.getData = function () {
$http.get('../ChatApp/data/data.json')
.then(function(response) {
$scope.data =response.data.messages;
console.log($scope.data);
});
};
//logout button
$scope.logout = function () {
localStorage.clear();
console.log(localStorage);
};
//function for rocket button
$scope.sendMessage = function (message) {
$scope.date = new Date();
$scope.date = $filter('date')(new Date(), 'HH:mm:ss');
$scope.message = null;
$scope.sendedMessage = message;
var audio = new Audio('../ChatApp/sounds/videoplayback');
audio.play();
};
//simple autentification
$scope.login = function () {
if(localStorage.getItem('Name') == null){
$state.go('login');
}
};
(function() {
$scope.getData();
$scope.login();
})();
});
app.controller('LoginController', function($scope, $state) {
//simple login
$scope.login = function (name) {
if(name == ""){
alert('Write your name! ');
}
else
{
localStorage.setItem('Name', $scope.name);
$state.go('home');
}
}
});
app.$inject = ['$scope'];
//When you click button rocket, you are adding this to html
app.directive("boxCreator", function($compile){
return{
restrict: 'A',
link: function(scope , element){
if(scope.sendedMessage != undefined && scope.sendedMessage!=null){
element.bind("click", function(e){
var childNode = $compile('<li class="self"><div class="msg"><div class="user">{{:: name}}</div><p>{{:: sendedMessage}}</p><time>{{:: date}}</time></div></li>')(scope);
angular.element( document.querySelector('#chat')).append(childNode);
});
}
//doStuff literally does nothing
scope.doStuff = function(){
alert('hey');
}
}
}
});
app.directive('myDirective', function() {
return {
compile: function(element, attr,$compile) {
var newElement = angular.element('<li class="other"><div class="msg"><div class="user">{{data[randomNumber].name}}</div><p>{{data[randomNumber].message}}</p><time>{{data[randomNumber].date}}</time></div></li>');
element.append(newElement);
var audio = new Audio('../ChatApp/sounds/videoplayback');
audio.play();
return function(scope, element, attr) {
setInterval(function () {
scope.$watch('data', function (data) {
console.log("fff", scope.data);
});
var newElement = angular.element('<li class="other"><div class="msg"><div class="user">{{name}}</div><p>{{scope.data[0].message}}</p><time>{{data[0].date}}</time></div></li>');
element.append(newElement);
var audio = new Audio('../ChatApp/sounds/videoplayback');
audio.play();
},5000);
}
}
}
});
});
Related
I have a Sharepoint list I'm trying to get items from and populate in an Angular app. When the page loads, nothing is loaded, if I click off the page and click back the data shows up. How can I get the items to load sooner, like before the page is initially loaded?
Here's my page controller.
app.controller("organizationsCtrl", ["$scope", "$rootScope", "$location", "$routeParams", "spService", "dataService",
function ($scope, $rootScope, $location, $routeParams, spService, dataService) {
$scope.editing = false;
$scope.column = "id";
$scope.reverse = false;
$scope.organizations = dataService.getOrganizations();
$scope.navToAdd = function() {
$location.path("/organizations/add");
}
$scope.navToEdit = function(index) {
$location.path("/organizations/" + index);
};
$scope.sortColumn = function(col) {
$scope.column = col;
if($scope.reverse) {
$scope.reverse = false;
//$scope.reverseclass = 'arrow-up';
} else {
$scope.reverse = true;
//$scope.reverseclass = 'arrow-down';
}
};
}
]);
Here is my service.
app.service('dataService', ['$rootScope', 'spService', function ($rootScope, spService) {
var svc = {};
var organizations = {};
svc.getOrganizations = function() {
spService.getRecords("Organizations", "?$select=ID,Title").then(function (result) {
organizations = result;
});
return organizations;
}
return svc;
}]);
This's my service. I've got variable isPolygonDrawingEnded there.
angular
.module('gillie.clients.app')
.service('mapDrawingService', mapDrawingService);
mapDrawingService.$inject = ['$ngBootbox', '$translate', 'fitPolygonService', 'mapCommonService'];
function mapDrawingService($ngBootbox, $translate, fitPolygonService, mapCommonService) {
var self = this;
var map;
var polygonFeatures;
var stopDrawingAction;
var isPolygonDrawingEnded = false;
var isDrawingMode = true;
self.startNewPolygonDrawing = function (afterDrowed) {
fitPolygonService.suggestPoint(isDrawingMode);
var modify = createModifyInteractionToPolygonFeatures();
var draw = createDrawInteraction();
attachDrawEvents(draw, afterDrowed);
map.addInteraction(draw);
stopDrawingAction = function() {
map.removeInteraction(draw);
map.removeInteraction(modify);
};
};
var attachDrawEvents = function (draw, afterDrowed) {
draw.on('drawend', function (e) {
e.preventDefault();
afterDrowed();
isPolygonDrawingEnded = true;
if (fitPolygonService.isPolygonsExist()) {
var geometry = e.feature.getGeometry();
e.feature.setGeometry(fitPolygonService.fitPolygon(geometry));
}
});
}
This is my controller. Here I need to change $scope.showCountButton when mapDrawingService.isPolygonDrawingEnded == true. So how can I know that value in service is changed ?
angular
.module('gillie.clients.app')
.controller('regionController', regionController);
regionController.$inject = ['$q', '$filter', '$scope', '$ngBootbox', '$translate', 'regionService', 'mapService', 'mapDrawingService', 'modalService', 'regionCommonService', 'alertService', 'nominatimCommonService', 'populationService', 'provinceCommonService', 'provinceService', 'rx'];
function regionController($q, $filter, $scope, $ngBootbox, $translate, regionService, mapService, mapDrawingService, modalService, regionCommonService, alertService, nominatimCommonService, populationService, provinceCommonService, provinceService, rx) {
$scope.showCountButton = false;
$scope.startRegionSelection = function (region) {
$scope.isSavingAvailable = true;
$scope.showCountButton = false;
if (currentEditingRegion && region && currentEditingRegion.Id === region.Id) {
return;
}
if(region)
mapService.clearRegion(region);
if (currentEditingRegion && !region) {
mapDrawingService.continuePolygonDrawing();
return;
}
if (region) {
mapDrawingService.stopPolygonDrawing();
mapDrawingService.clearMap();
currentEditingRegion = region;
mapDrawingService.startExistPolygonDrawing(region.Name, region.CoordinatesJson);
return;
}
mapDrawingService.startNewPolygonDrawing(function () {
$scope.showCountButton = true
});
};
When I use mapDrawingService.startNewPolygonDrawing function - the value of showCountButton changes but view doesn't. $scope.$apply produces this exception:
[$rootScope:inprog] $digest already in progress
When you are passing the callback function it is no longer in the scope of the controller which is why the view is not updating. You can use promises instead since you are asynchronous draw event.
Service
mapDrawingService.$inject = ['$q', '$ngBootbox', '$translate', 'fitPolygonService', 'mapCommonService'];
function mapDrawingService($q, $ngBootbox, $translate, fitPolygonService, mapCommonService) {
var self = this;
var map;
var polygonFeatures;
var stopDrawingAction;
var isPolygonDrawingEnded = false;
var isDrawingMode = true;
self.startNewPolygonDrawing = function() {
fitPolygonService.suggestPoint(isDrawingMode);
var modify = createModifyInteractionToPolygonFeatures();
var draw = createDrawInteraction();
var promiseObj = attachDrawEvents(draw);
map.addInteraction(draw);
stopDrawingAction = function() {
map.removeInteraction(draw);
map.removeInteraction(modify);
};
return promiseObj;
};
var attachDrawEvents = function(draw) {
return $q(function(resolve, reject) {
draw.on('drawend', function(e) {
e.preventDefault();
if (fitPolygonService.isPolygonsExist()) {
var geometry = e.feature.getGeometry();
e.feature.setGeometry(fitPolygonService.fitPolygon(geometry));
}
resolve();
});
});
}
Controller
mapDrawingService.startNewPolygonDrawing().then(function() {
$scope.showCountButton = true
});
I have a $stateChangeStart event trigger whenever user navigate between the templates, so in below code when user change a state i am deleting $scope.filename that is working as expected but when i go back to that page its throwing a exception and i lose socket.io connection because $scope.filename value is still there that is executing if statement. How can i destroy $scope value in this case ?
ctrl.js
angular.module('loggingApp').controller('DitCtrl', function($scope, $rootScope, DitFactory, FileSaver, Blob, socket, $uibModal, searchFactory) {
'use strict';
$scope.event = [];
$scope.disabledRecBtn = false;
$scope.disabledStopBtn = true;
$scope.showMessage = false;
var totalCurrentBytes = [];
$scope.curVal = 4000;
$scope.maxVal = 37737;
//ENDS HERE
var sendMessageFlag = false;
// Delete File method
function deleteFile(filename) {
DitFactory.getFile(filename).then(function(response, $window) {
console.log('data for download', response);
var data = JSON.stringify(response.data);
var blob = new Blob([data], {
type: 'text/plain;charset=utf-8'
});
FileSaver.saveAs(blob, 'server.log');
socket.emit('stopRecording', $scope.filename);
});
}
socket.on('ditConsumer', function(data) {
var obj = {
file: $scope.filename,
data: data
}
$scope.event.push(data);
jsonToArray();
socket.emit('messageToFile', obj);
if (sendMessageFlag === true) {
return sendMessageToFile(obj);
}
});
function sendMessageToFile(data) {
if (data.file) {
socket.emit('startrecording', data);
$scope.disabledRecBtn = true;
$scope.disabledStopBtn = false;
$scope.showMessage = true;
}
}
$scope.stopLogs = function() {
sendMessageFlag = false;
$scope.modalInstance = $uibModal.open({
templateUrl: '/web/global/modal.html',
controller: 'ModalController'
});
};
$rootScope.$on('downloadFile', function(s, data) {
deleteFile($scope.filename);
$scope.disabledRecBtn = false;
$scope.disabledStopBtn = true;
$scope.showMessage = false;
});
$rootScope.$on('onCancelDelete', function() {
if ($scope.filename) {
console.log('oncanceldelete function');
socket.emit('stopRecording', $scope.filename);
$scope.disabledRecBtn = false;
$scope.disabledStopBtn = true;
$scope.showMessage = false;
}
});
$scope.recordLogs = function() {
socket.emit('createlogfile');
socket.on('filename', function(filename) {
console.log('filename from sever', filename);
$scope.filename = filename;
sendMessageFlag = true;
$scope.disabledRecBtn = true;
$scope.disabledStopBtn = false;
$scope.showMessage = true;
});
}
//Search logs code here
$scope.searchLogs = function() {
$scope.modalInstance = $uibModal.open({
templateUrl: '/view/modals/searchModal.html',
controller: 'SearchController'
});
searchFactory.setDitLogs($scope.event);
}
$scope.serverFiles = function() {
$scope.modalInstance = $uibModal.open({
templateUrl: '/view/modals/serverModal.html',
controller: 'ServerFilesCtrl'
})
}
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
if($scope.filename) {
console.log($scope.filename);
console.log('STATE CHANGED');
console.log('destroy on close');
socket.emit('stopRecording', $scope.filename);
sendMessageFlag = false;
$scope.filename = null;
}
})
});
All the scopes are destroyed when a routing is done. That is the feature that ui- router comes with. If you want to manually specify it for a certain purpose you can always use $scope.$destroy for certain controllers.
when i go back to state all methods are invoking twice e.g $scope.recordLogs printing console.log('filename from sever', filename);
The console.log is part of the handler function that has been given to the socket service. Even though the $scope has been destroyed, the socket.on handler function has been saved by the socket service.
$scope.recordLogs = function() {
socket.emit('createlogfile');
//PROBLEM
//event handler function retained by socket service
socket.on('filename', function(filename) {
console.log('filename from sever', filename);
$scope.filename = filename;
sendMessageFlag = true;
$scope.disabledRecBtn = true;
$scope.disabledStopBtn = false;
$scope.showMessage = true;
});
}
To avoid duplicating event handlers when a user navigates back and forth between routes use socket.forward:
angular.module('myMod', ['btford.socket-io']).
controller('MyCtrl', function ($scope, socket) {
socket.forward('someEvent', $scope);
$scope.$on('socket:someEvent', function (ev, data) {
$scope.theData = data;
});
});
By using socket.forward, the socket service will unregister the handler when the $scope gets destroyed.
For more information, see angular-socket-io API Reference - socket.forward
I have this variable that is being controlled by the Factory and to update the Controller but it's not happening.
Here is what I have:
var app = angular.module('plunker', []);
app.controller('AppController', function($scope, AppFactory) {
var vm = this;
$scope.serverStatus = AppFactory.getStatus();
});
app.factory('AppFactory', function($timeout) {
var AppFactory = {};
var vm = this;
vm.serverStatus = true;
// Execute after 2 seconds of page start
$timeout(function() {
AppFactory.setStatus(false);
}, 2000);
AppFactory.setStatus = function(status) {
console.log('Server set to ' + status);
vm.serverStatus = status;
// Getting server status = false
AppFactory.getStatus();
};
AppFactory.getStatus = function() {
console.log('Getting server status: ' + vm.serverStatus);
return vm.serverStatus;
};
return AppFactory;
});
LIVE PLUNKER DEMO: https://plnkr.co/edit/62xGw7Klvbywp9TODWF4?p=preview
Do you think Directives would work better with 2-way-communication between a factory and controller?
Check this edited the plunkr https://plnkr.co/edit/z6tdr5?p=preview
var app = angular.module('plunker', []);
app.controller('AppController', function($scope,$timeout, AppFactory) {
var vm = this;
$timeout(function() {
AppFactory.setStatus(false);
$scope.serverStatus = AppFactory.getStatus();
}, 2000);
$scope.serverStatus = AppFactory.getStatus();
});
app.factory('AppFactory', function($timeout) {
var AppFactory = {};
var serverStatus = true;
// Execute after 2 seconds of page start
return {
getStatus: function () {
//console.log('Getting server status: ' + vm.serverStatus);
return serverStatus;
},
setStatus : function(status) {
var vm = this;
console.log('Server set to ' + status);
serverStatus = status;
// Getting server status = false
vm.getStatus();
}
};
});
Here's a solution that uses events, e.g.:
app.controller('AppController', function($scope, AppFactory) {
var vm = this;
$scope.$on('messageOne', function(event, data){
console.log(data);
$scope.serverStatus = data;
$scope.$apply(); //I think $apply() is not needed here!
});
$scope.serverStatus = AppFactory.getStatus();
});
app.factory('AppFactory', function($timeout, $rootScope) {
var AppFactory = {};
var vm = this;
vm.serverStatus = true;
// Execute after 2 seconds of page start
$timeout(function() {
AppFactory.setStatus(false);
}, 2000);
AppFactory.setStatus = function(status) {
console.log('Server set to ' + status);
vm.serverStatus = status;
// Getting server status = false
//AppFactory.getStatus();
$rootScope.$broadcast('messageOne', status);
};
AppFactory.getStatus = function() {
console.log('Getting server status: ' + vm.serverStatus);
return vm.serverStatus;
};
return AppFactory;
});
https://plnkr.co/edit/pARMnE3Wl0OeJezKuvLT?p=info
I have an angular function that allows to drop a text file into a textarea and the contents are placed into the textbox. The issue is this does not work in Firefox. Any ideas?
PLunkr
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.text = "";
})
.directive('plkrFileDropZone', [function () {
return {
restrict: 'EA',
scope: {content:'='},
link: function (scope, element, attrs) {
scope.content = "drop a .txt file here";
var processDragOverOrEnter;
processDragOverOrEnter = function (event) {
if (event !== null) {
event.preventDefault();
}
event.dataTransfer.effectAllowed = 'copy';
return false;
};
element.bind('dragover', processDragOverOrEnter);
element.bind('dragenter', processDragOverOrEnter);
element.bind('drop', handleDropEvent);
function insertText(loadedFile) {
scope.content = loadedFile.target.result;
scope.$apply();
}
function handleDropEvent(event) {
if (event !== null) {
event.preventDefault();
}
var reader = new FileReader();
reader.onload = insertText;
reader.readAsText(event.dataTransfer.files[0]);
}
}
};
}]);
There is an easier solution remove the line
event.dataTransfer.effectAllowed = 'copy';