Has anyone been able to pause / resume sync using Angular fire?
New to the Firebase/ AngularJS (Angularfire) stuff.
I've try nulling the objects and re initializing them on the click of a button but it doesnt do anything,
Thanks for any input.
Steve
Code as requested
var app = angular.module("imageanalyser-app", ["firebase"]);
var ref = null;
function MyController($scope, $firebase) {
ref = new Firebase("...");
$scope.messages = $firebase(ref.endAt().limit(100));
}
function resumeSync() {
$("#btnResume").click(function() {
ref = new Firebase("...");
});
}
function stopSync() {
$("#btnStop").click(function () {
ref = null;
});
}
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div ng-app="imageanalyser-app">
<div id="links" class="container-fluid" ng-controller="MyController">
<div ng-repeat="msg in messages" class="gallery-item-container">
<a href="{{msg.highResUrl}}" data-gallery>
<img ng-src="{{msg.Source}}" height="20" width="20" style="position: absolute"/>
<img ng-src="{{msg.imgUrl}}" class="gallery-item-image" />
</a>
<div class="gallery-item-tags" ng-repeat="tag in msg.tags">{{tag}}</div>
</div>
</div>
</div>
</div>
You're updating ref, but never changing $scope.messages. The ng-repeat is based on $scope.messages, so it won't change either!
To get this to behave as you want you'll need to affect the messages variable.
This worked for me, using the $off() to stop sync and then reinitialize it.
var fireBaseRef;
var synced = true;
function MyController($scope, $firebase) {
fireBaseRef = new Firebase("......");
$scope.messages = $firebase(fireBaseRef.endAt().limit(100));
jQuery("#btnToggleState").click(function () {
if (synced) {
$scope.messages.$off();
synced = false;
} else {
$scope.messages = $firebase(fireBaseRef.endAt().limit(100));
synced = true;
}
});
}
Related
I started with this simple plunkr
From what I can tell it only uses one component. I have a project that uses multiple components. I have a cart and users clicks add button to add items to said cart. The check out component just empties the cart. I expect that when the cart is empty, the display also empties and the total would show 0.00, but that is not happening. From what I can tell the HTML only changes page load not on change of data and that is the problem, but it was my understanding that angular would take care of this on its own.
Thanks in advance
Relevant code:
app.config.js (this file has the factory and checkout functionality)
'use strict';
angular.
module('floorForceApp').
config(['$routeProvider', '$provide',
function config($routeProvider,$provide) {
$routeProvider.
when('/home', {
template: '<home-page></home-page>'
}).
when('/floors', {
template: '<floor-page></floor-page>'
}).
when('/cabinets', {
template: '<cabinet-page></cabinet-page>'
}).
when('/walls', {
template: '<wall-page></wall-page>'
}).
when('/checkout', {
template: '<checkout-page></checkout-page>'
}).
otherwise('/home');
},
]).factory('floorForceCart',function(){
let total = 0;
let addedItems = [];
// let additem = function(item,price){
// }
return{
addItems:function(item,count){
let exist =false;
$.each(addedItems,function(i,v){
if(v.itemNo === item.itemNo){
exist = true;
v.count = v.count + count;
total = total + (item.itemPrice*count);
}
});
if(!exist){
let toPush = {};
toPush.itemNo = item.itemNo;
toPush.count = count;
toPush.itemName = item.itemName;
toPush.itemPrice = item.itemPrice;
addedItems.push(toPush);
total = total + (item.itemPrice*count);
}
console.log("Cart:",addedItems);
console.log("Total:",total);
},
removeItems: function(item,count){
$.each(addedItems,function(i,v){
if(v.itemNo === item.itemNo){
v.count = v.count - count;
total = total - (item.itemPrice * count);
if(v.count == 0){
addedItems.splice(i,0);
}
}
});
},
getTotal:function(){
return total;
},
getCart:function(){
return addedItems;
},
checkout:function(){
total = 0;
addedItems = [];
console.log("Check out successful.");
console.log("Total:",total,"Cart:",addedItems);
alert("Checkout Successful!");
}
};
});
checkout-page.component.js (data is loaded from factory to here)
'use strict';
angular.
module('checkoutPage').
component('checkoutPage',{
templateUrl: 'checkout-page/checkout-page.template.html',
controller: function checkOutController($scope,$http,floorForceCart){
let self = this;
$scope.total = floorForceCart.getTotal();
$scope.cart = floorForceCart.getCart();
$scope.checkOut = function(){
floorForceCart.checkout();
}
}
})
checkout-page.html (this page displays the checkout)
<div>
<div style="height:30em;">
<div class="container-fluid h-100">
<div class="row h-100">
<div class="col-sm-4 h-100 ">
<div class="row prodImage h-100"></div>
</div>
<div class="col-sm-8 h-100 ">
<div class="row h-100">
<div class="checkOutTitleDiv titleDiv">Checkout</div>
<div class="checkOutCartDiv paddingZero">
<div ng-repeat="item in cart" class="row marginAuto cartItemRow">
<div class="itemNameDiv col-sm-5">{{item.itemName}}</div>
<div class="itemPriceDiv col-sm-3">{{item.itemPrice|currency}}</div>
<div class="itemQuantityDiv col-sm-4">
<div class="row">
<div class="col-sm-4"></div>
<div class="col-sm-4 itemQuantity">{{item.count}}</div>
<div class="col-sm-4"></div>
</div>
</div>
</div>
</div>
<div class="checkOutButtonDiv paddingZero">
<div class="row h-100 marginAuto">
<div class="col-sm-4 cartTotalDiv">
<div class="">Total:{{total|currency}}</div>
</div>
<div class="col-sm-4"></div>
<div class="col-sm-4">
<input class="checkOutButton btn btn-success" ng-click="checkOut()" type="button"value="Check Out"/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
It is because in the controller you add a property in the $scope referencing the same array of items referenced by the addedItems variable in the factory:
$scope.total = floorForceCart.getTotal();
$scope.cart = floorForceCart.getCart();
Then, when you call checkout from the factory, you re-assign the addedItems variable from the factory to a new array, and you assign a 0 to the total variable. The problem is that the properties $scope.total and $scope.cart doesn't have any way of knowing this. $scope.cart will still be pointing to the old array with items.
You could solve this by either:
Changing your $scope.checkOut to
$scope.checkOut = function(){
floorForceCart.checkout();
// And refresh your $scope
$scope.total = floorForceCart.getTotal();
$scope.cart = floorForceCart.getCart();
}
Or by instead of assigning a new array to addedItems in the factory, clearing it using:
addedItems.length = 0;
If you go with the last approach, you would still have to do $scope.total = floorForceCart.getTotal(); after floorForceCart.checkout(); to update the total in your $scope.
I have three .js files here. This code works fine except the count scores don't correlate with the other clicking of the button. I would like to add these requirements to my code as well: Each service will store the counter that displays above/below the buttons as a property on the service. Each service will have at least 3 methods: increment, decrement, and reset, which resets the counter to 100.
The counter property in the services must NOT be directly manipulated by a controller - you should create public methods in your services to perform the operations instead, which are called by the controller.
//home.js
var app = angular.module('MyApp');
app.controller("HomeController", ['$scope', 'RedService', 'BlueService', function ($scope, $rs, $bs) {
$scope.title = "The Mighty Clicker";
$scope.redOutput = 100;
$scope.blueOutput = 100;
$scope.countRed = function () {
$rs.countUp++;
$scope.redOutput = $rs.countUp;
$bs.coundDown--;
$scope.blueOutput = $bs.coundDown;
}
$scope.countBlue = function () {
$bs.countUp++;
$scope.blueOutput = $bs.countUp;
$rs.countDown--;
$scope.redOutput = $rs.countDown;
}
}]);
//blueService.js
var app = angular.module("MyBlueService", []);
app.service("BlueService", function () {
this.countUp = 100;
this.coundDown = 100;
})
//redService.js
var app = angular.module("MyRedService", []);
app.service("RedService", function() {
this.countUp = 100;
this.countDown = 100;
})
here is my HTML code
//html
<div class="row">
<div class="col-xs-12 buttons">
<h1 class='title'>{{title}}</h1>
<button class="btn red" ng-click="countRed()">Button</button>
<h1>{{redOutput}}</h1>
<br><br><br><br><br><br>
<button class="btn blue" ng-click="countBlue()">Button</button>
<h1>{{blueOutput}}</h1>
</div>
</div>
enter image description here
Not exactly sure what the rules are but from what I understand I made a plunker:
https://plnkr.co/edit/lrMgM8lcm0FtCIQbZLlf?p=preview
It looks like the code works without needing change except for the typos :D
$scope.blueOutput = blueService.countDown;
You mispelled countDown with coundDown
As #gyc mentioned in his post, there was a typo. I have created the plunkr with the same design architecture (3 modules and each of them with a service).
RedApp and BlueApp modules are added to MainApp module as dependencies and used their in myApp's controller.
var myApp = angular.module("MainApp", ["RedApp", "BlueApp"]);
myApp.controller("MyAppController", ["$scope", "RedAppService", "BlueAppService", function($scope, $rs, $bs) {
$scope.title = "The Mighty Clicker";
$scope.redOutput = 100;
$scope.blueOutput = 100;
$scope.countRed = function() {
$rs.countUp++;
$scope.redOutput = $rs.countUp;
$bs.countDown--;
$scope.blueOutput = $bs.countDown;
}
$scope.countBlue = function() {
$bs.countUp++;
$scope.blueOutput = $bs.countUp;
$rs.countDown--;
$scope.redOutput = $rs.countDown;
}
}]);
var redApp = angular.module("RedApp", []);
var blueApp = angular.module("BlueApp", []);
redApp.service("RedAppService", function() {
this.countUp = 100;
this.countDown = 100;
});
blueApp.service("BlueAppService", function() {
this.countUp = 100;
this.countDown = 100;
});
As I understand You need to have two buttons, if click first -> it counter gets up and counter second one gets down. I have done it by starting from Your code, but I've simplified the solution, so both services has only one counter and I set services directly into scope to avoid many assignments and variables. Check my working example:
//home.js
var app = angular.module('MyApp',[]);
app.controller("HomeController", ['$scope', 'RedService', 'BlueService', function ($scope, $rs, $bs) {
$scope.title = "The Mighty Clicker";
//services to scope directly
$scope.$rs=$rs;
$scope.$bs=$bs;
$scope.countRed = function () {
$rs.count++;
$bs.count--;
}
$scope.countBlue = function () {
$bs.count++;
$rs.count--;
}
}]);
//blueService.js
app.service("BlueService", function () {
this.count = 100;//single counter
})
//redService.js
app.service("RedService", function() {
this.count = 100; //single counter
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp" ng-controller="HomeController" class="row">
<div class="col-xs-12 buttons">
<h1 class='title'>{{title}}</h1>
<button class="btn red" ng-click="countRed()">Button</button>
<h1>{{$rs.count}}</h1>
<button class="btn blue" ng-click="countBlue()">Button</button>
<h1>{{$bs.count}}</h1>
</div>
</div>
EDIT. AFTER COMMENT.
//home.js
var app = angular.module('MyApp',[]);
app.controller("HomeController", ['$scope', 'RedService', 'BlueService', function ($scope, $rs, $bs) {
$scope.title = "The Mighty Clicker";
//services to scope directly
$scope.$rs=$rs;
$scope.$bs=$bs;
$scope.countRed = function () {
$rs.increment();
$bs.decrement();
}
$scope.countBlue = function () {
$bs.increment();
$rs.decrement();
}
$scope.reset=function(){
$bs.reset();
$rs.reset();
}
}]);
//return constructor
//create for DRY
app.service("Counter",function(){
return function(){
this.count = 100;//single counter
this.increment=function(){
this.count++;
};
this.decrement=function(){
this.count--;
};
this.reset=function(){
this.count=100;
};
};
});
//blueService.js
app.service("BlueService", ["Counter",function ($cf) {
return new $cf;
}]);
//redService.js
app.service("RedService", ["Counter",function ($cf) {
return new $cf;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="MyApp" ng-controller="HomeController" class="row">
<div class="col-xs-12 buttons">
<h1 class='title'>{{title}}</h1>
<button class="btn red" ng-click="countRed()">Button</button>
<h1>{{$rs.count}}</h1>
<button class="btn blue" ng-click="countBlue()">Button</button>
<h1>{{$bs.count}}</h1>
<button ng-click="reset()">Reset counters</button>
</div>
</div>
View is not updating even if model gets updated. I googled about this problem and i got some solution, that use setTimeout or $timeout function.
I tried above function, but even using $timeout function model gets updated and view is not.
I am setting value of model from one service. When one controller setting value in service another controller listens to that service and update its model.
Note Factory Service
function loadNoteFactory($http) {
var baseURL = "SOME_URL";
var sessionId = "sessionId";
return {
getNotes: function() {
return $http.get(baseURL+"notes?"+sessionId);
},
addNote: function(note) {
return $http.post(baseURL+"note?"+sessionId, note);
},
editNote: function(tag, tagname) {
return $http.put(baseURL +"note/"+ note.id+"?"+sessionId, note);
},
deleteTag: function(tagId) {
return $http.delete(baseURL +"note/"+ note.id+"?"+sessionId);
}
};
}
Factory service
function loadSelectedNoteFactory($rootScope){
var selectedNoteFactory = {};
selectedNoteFactory.note = {};
selectedNoteFactory.setCurrentNote = function(note) {
this.note = note;
$rootScope.$broadcast('noteChanged');
};
return selectedNoteFactory;
}
Contoller 1 - Setting new value in service
function loadNoteListControllar($scope, NoteFactory, tagBasedNoteSearchService, selectedNoteFactory){
getUsersNotes();
function getUsersNotes(){
NoteFactory.getNotes().success(function(data) {
$scope.notes = data.notes;
selectedNoteFactory.setCurrentNote($scope.notes[0]);
});
}
$scope.onSelectNote = function(note){
selectedNoteFactory.setCurrentNote(note);
}
}
Controller 2 - update itself on change in service
function loadDetailControllar($scope, $timeout, selectedNoteFactory){
$scope.note = {};
$scope.$on('noteChanged', testme);
function testme(){
$timeout(function(){
$scope.note = selectedNoteFactory.note;
}, 500);
}
}
Html
<div class="tagWidget" ng-app="tagWidget">
<div class="notelistcontainer floatleft" ng-controller="NoteListController" style="width: 20%; height: 100%;">
<div class="notelist" style="border: solid 5px grey;">
<div class="noteitem greyborderbottom" ng-repeat="note in notes">
<div class="paddinglefttwentypx notesubject attachdotdotdot widthhundredpercent" ng-click="onSelectNote(note)">{{::note.subject}}</div>
</div>
</div>
</div>
<div class="detailview floatright" ng-controller="DetailController" style="width: 60%; height: 100%;">
<div class="paddinglefttwentypx notetext attachdotdotdot widthhundredpercent">{{::note.notehtmltext}}</div>
</div>
</div>
</div>
Injecting Cotroller, Services and Directives
angular.module('tagWidget', [])
.factory('tagBasedNoteSearchService', loadTagBasedNoteSearchService)
.factory('NoteFactory', loadNoteFactory)
.factory('SelectedNoteFactory', loadSelectedNoteFactory)
.directive('editableDiv', loadEditableDiv)
.directive('toggleIcon', loadToggleIcon)
.controller('NoteListController', ['$scope', 'NoteFactory', 'tagBasedNoteSearchService', 'SelectedNoteFactory', loadNoteListControllar])
.controller('DetailController', ['$scope', '$timeout', 'SelectedNoteFactory', loadDetailControllar])
'tagBasedNoteSearchService', 'SelectedNoteFactory', loadTagControllar]);
Solution - removed :: from expression {{::note.notehtmltext}}
How can i pass html through in AngularJS controller ?
Here is my list.html:
<div class="col-xs-3" ng-repeat="item in companyData">
<a ng-click="getPackageInfo({{item.iCompanyID}},'{{item.vCompanyName}}')" class="block panel padder-v bg-primary item">
<span class="text-white block">{{item.vCompanyName}}</span>
</a>
<div id="packagehtml"></div>
</div>
<div id="lp" class="col-md-12 listing-div hidden"></div>
in controller.js:
$scope.pData = [];
$scope.getPackageInfo = function(id,name) {
$scope.name = name;
var summery = SubscriptionoptioncompanylistFactory.getSummary(id);
document.getElementById("lp").classList.remove("hidden");
$('.packages-data').html('');
$('#loading').show();
SubscriptionoptioncompanylistFactory.getPackageInDetail(id).
success(function(data) {
if(data != 0) {
$("#lp").html(summery); // this is used to append the data
document.getElementById("np").classList.add("hidden");
Array.prototype.push.apply($scope.pData, data);
$('#loading').hide();
} else {
document.getElementById("lp").classList.add("hidden");
document.getElementById("np").classList.remove("hidden");
$('#loading').hide();
}
});
};
Here, I have wrote $("#lp").html(summery);, in that div I have to append html which comes from var summery = SubscriptionoptioncompanylistFactory.getSummary(id);. But this is not going to append the data. In console I can see that data comes in summary variable. How can I do?
have a look at below modifications
Use angular ng-show for showing/hiding elements
Use data binding and avoid Jquery like Dom manipulation
<div class="col-xs-3" ng-repeat="item in companyData">
<a ng-click="getPackageInfo({{item.iCompanyID}},'{{item.vCompanyName}}')" class="block panel padder-v bg-primary item">
<span class="text-white block">{{item.vCompanyName}}</span>
</a>
<div id="packagehtml"></div>
</div>
<div id="lp" ng-show="lbVisible" class="col-md-12 listing-div hidden">{{summaryBinding}}</div>
and the controller would look like :
$scope.pData = [];
$scope.getPackageInfo = function (id, name) {
$scope.name = name;
var summery = SubscriptionoptioncompanylistFactory.getSummary(id);
$scope.lbVisible = true; //document.getElementById("lp").classList.remove("hidden");
$('.packages-data').html('');
$scope.loadingVisible = true; //$('#loading').show();
SubscriptionoptioncompanylistFactory.getPackageInDetail(id).
success(function (data) {
if (data != 0) {
$scope.summaryBinding = summery; // $("#lp").html(summery); // this is used to append the data
$scope.npVisible = false; // document.getElementById("np").classList.add("hidden");
Array.prototype.push.apply($scope.pData, data);
$scope.loadingVisible = false; // $('#loading').hide();
} else {
$scope.lbVisible = false; //document.getElementById("lp").classList.add("hidden");
$scope.npVisible = false; //document.getElementById("np").classList.remove("hidden");
$scope.loadingVisible = false; // $('#loading').hide();
}
});
};
your snippet is not showing elements that you use :
np, #loading so just find them and add the `ng-show` with the proper scope variable : `npVisible , lbVisible , loadingVisible`
and note that we add the data using summaryBinding
hope this helps :)
Hey guys I wonder if there's a solution on this mess I normally create in Angular projects:
app.controller('indexController', function ($scope) {
scope.hideWinkelContainer = true;
scope.hideWinkelPaneel = true;
scope.headerCart = false;
scope.showCart = function () {
scope.hideWinkelContainer = false;
scope.hideWinkelPaneel = false;
};
scope.hideCart = function () {
scope.hideWinkelContainer = true;
scope.hideWinkelPaneel = true;
};
});
html:
<div class="containerWinkelwagen" ng-hide="hideWinkelContainer"> <div class="winkelWagenPaneel" ng-hide="hideWinkelPaneel">
<div class="winkelWagenTerug" ng-click="hideCart()"></div>
<div class="winkelWagenTerug" ng-click="showCart()"></div>
</div>
</div>
Best practices, tips, examples are always welcome!
You can simply use a toggle function as follow:
app.controller('indexController', function ($scope) {
$scope.hideWinkelContainer = true;
$scope.hideWinkelPaneel = true;
$scope.headerCart = false;
$scope.toggleCart = function () {
$scope.hideWinkelContainer = !$scope.hideWinkelContainer;
$scope.hideWinkelPaneel = !$scope.hideWinkelPaneel;
};
});
In your HTML:
<div class="containerWinkelwagen" ng-hide="hideWinkelContainer">
<div class="winkelWagenPaneel" ng-hide="hideWinkelPaneel">
<div class="winkelWagenTerug" ng-click="toggleCart()"></div>
<div class="winkelWagenTerug" ng-click="toggleCart()"></div>
</div>
</div>
You can implement the show/hide functions once in a factory, and then inject it into the controllers that need it. Saves a lot of boilerplate.