AngularJS - Share scope value between controllers - javascript

I have a textarea in my HTML like this:
<textarea ng-model="commentBox"></textarea>
To access this i simply use "$scope.commentBox" in my controller. But my question is, how do i access the same commentBox within a different controller?
I do have a factory/service setup for this purpose, but i cant figure out how to get the commentBox value in there, for my other controller to use it.
In my factory i have an object var saved = {} and I want to add a property called "comment", with the value of whatever is inside the textarea. Like this saved.comment = commentbox And then access that value from the other controller.
I'm still new at Angular and tried to send the scope information in a parameter to the facory.
var saved = {};
factory.addComment = function (commentbox) {
saved.comment = commentbox
}
Then have my controller send the scope information on a button click,
$scope.testFunction = function () {
myFactory.addComment($scope.commentBox);
}
But yeah, that did not work out.
Note that i need this to work within the factory, and not by using another ng-controller in the HTML.

You need to return your saved var in your factory
var saved = {};
factory.addComment = function (commentbox) {
saved.comment = commentbox
}
return saved
Here there is an example using a service
app.service('fakeService', function() {
var savedData = {};
var addComment = function(newComment) {
savedData.commnet = newComment;
};
var getComment = function(){
return savedData.comment;
};
return {
addComment: addComment,
getComment: getComment
};
});
To inject a factory/service in your controller
app.controller('fakeController', ['$scope','yourFactory',function ($scope, yourFactory) {
console.log(yourFactory.comment) // here you should log saved comment
}])
Then in your controller, you can inject the factory/service and access to saved data. But remember, is your refresh your page, data will be lost, so, to avoid that, you should persist data on your DB.

Related

Returning additional table data that is already in the ASP.NET API with Angular

I have a returned api with a ASP.NET Model in Visual studios. I updated the model by adding a table that has no relationship to my first model except that it's a table with a list of data like, states, or something similar that I want to use for a drop down in Angular.
I currently have
app.factory('ComplaintService', ['$http', function ($http){
var urlBase = 'http://localhost:63942/api';
var ComplaintService = {};
ComplaintService.getCities = function () {
return $http.get(urlBase+ '/complaints');
};
return ComplaintService;
}]);
How would I implement or extend the factory so that in addition to returning the ComplaintService, I also want it to return AllegationService:
return $http.get(urlBase+ '/allegations').
I am very confused on when to use a factory or a service. I then want to pass the AllegationService to a 'AllegationList' controller then returns data that will be placed into a drop down.
You don't need to create a separate factory for allegations. you can just add another factory method to get list of allegations or whatever type of data it is.
app.factory('Service', ['$http', function ($http){
var urlBase = 'http://localhost:63942/api';
var Service = {};
Service.getComplaints = function () {
return $http.get(urlBase+ '/complaints');
};
Service.getAllegations = function () {
return $http.get(urlBase+ '/allegations');
};
return Service;
}]);

AngularJS - Using Model in Controller causing Model to update

I have an Angular application where in I'm pulling from a model some data which is saved on the load of the app. For simplicity sake, I've explicitly defined the data which is being pulled.
The issue I have is that in one of my controllers I am running a function on load of the controller which modifies the data pulled from the model. The point is that I want that extra data for that page which is using that controller only. I don't want that data to be saved back into the model (which is what's happening).
My model:
'use strict';
(function () {
var PotsMod = function ($log, _) {
return {
pots: [
{"comp" : "comp1"},
{"comp" : "comp2"}
],
getPots: function () {
return this.pots;
},
};
};
angular
.module('picksApp.models')
.factory('PotsMod', PotsMod);
})();
My controller:
(function () {
function AdmCtrl($log, $routeParams, PotsMod) {
var vm = this;
vm.pots = PotsMod.getPots();
vm.init = function() {
// populate pot.competition
_.forEach(vm.pots, function(pot) {
pot.comp = "test";
});
console.log(PotsMod.getPots());
}
vm.init();
}
angular
.module('picksApp.controllers')
.controller('AdmCtrl', AdmCtrl);
})();
The final line in vm.init(), PotsMod.getPots(), returns to me the updated model, with the values of "comp" as test.
So I tried this instead - I put the debug line under vm.pots like so:
var vm = this;
vm.pots = PotsMod.getPots();
console.log(vm.pots);
vm.init = function() {....
This also returns to me the array where the object values are test...
So I tried one final thing and added an extra debug line in the vm.init() function too:
var vm = this;
vm.pots = PotsMod.getPots();
console.log(vm.pots);
vm.init = function() {
// populate pot.competition
_.forEach(vm.pots, function(pot) {
console.log(pot.comp);
pot.comp = "test";
});
console.log(PotsMod.getPots());
}
vm.init();
The result of this confuses me... The output in the console reads:
[{"comp":"test"},{"comp","test"}]
comp1
comp2
[{"comp":"test"},{"comp","test"}]
I must be missing something here because I don't understand how it can be defining a variable using a model's value, printing that variable with the updated values, then using the old values and printing them, then printing the updated values again from the model (even though nothing in this code touches the model).
Any help would be brilliant please, I see to be making a fundamental mistake somewhere. Thank you.
You're referencing the service's pots object in your controller, so your controller code is also modifying the service's code.
I created a Plunker to demonstrate how angular.copy() creates a deep copy of your service's 'pots', and thus your controller's model is no longer referencing the original.
In your case, all you need to change is vm.pots = angular.copy(getPots());
http://plnkr.co/edit/jg5mWIWds1KMJd51e3o5?p=preview

knockout cross view model

var barcodeNum = ko.observable("");
VelocityMeetings.scan = function (params) {
var errorMessage = ko.observable("");
var viewModel = {
errorMessage: errorMessage,
scannumber: ko.observable(""),
errorVisible: ko.computed(function () {
return errorMessage().length != 0;
}),
scanBarcode: function () {
//Capture image with device and process into barcode
capturePhoto();
this.scannumber(barcodeNum());
//this.errorMessage(errMessage);
},
};
return viewModel;
};
I have the barcodeNum variable created outside of the view model, to try and pass data back into the scannumber variable. How do I access a variable defined inside of a view model?
The goal is to use the javascript Worker I have, to update the scannumber which will update my app accordingly, but I can't get it to function properly.
function receiveMessage(e) {
barcodeNum("Test function");
}
var DecodeWorker = new Worker("js/BarcodeScanner.js");
DecodeWorker.onmessage = receiveMessage;
The goal is something along the lines of this
VelocityMeetings.scan.viewModel.scannumber(barcodeNum());
but this isnt working properly
When you find yourself working with separate view models that have to communicate with each other, consider using knockout-postbox. You can make the communication one-way or two-way if you want. In your case, I think a one-way communication will be enough.
var barcodeNum = ko.observable('').publishOn('barcodeNum');
var viewModel = {
scannumber: ko.observable().subscribeTo('barcodeNum'),
// ...
};
I found the issue my self
scannumber: ko.observable(""),
scannumber can be defined as ko.computed with the return value being barcodeNum(), that will make any change made to barcodeNum also made to scannumber()
here is my computed
scannumber: ko.computed(function () { return barcodeNum(); },this),
I have been through this problem a lot of times before.. Then I decided to write an article on same...
You can refer to this article : http://www.wrapcode.com/knockoutjs/communication-between-multiple-view-models-in-knockoutjs-mvvm-the-right-approach/
I have explained how to deal with multiple view models and separate instances of multiple view models in this article..
Hope others will find it helpful :-)

How to pass a http request result in my case?

I am trying to get the http request result to my child controller.
I have something like
<div ng-controller = "parentCtrl">
<button ng-click="callApi()">click me</button>
<div ng-controller = "childCtrl">
<div>{{productDetail}}</div>
</div>
</div>
angular.module('App').controller('parentCtrl', ['$scope','myFactory',
function($scope, myFactory) {
$scope.callApi = function() {
myFactory.request(id)
.then(function(data) {
$scope.productDetail = data
//do something in parent controller here....
})
}
}
]);
angular.module('App').controller('childCtrl', ['$scope',
function($scope) {
//I am not sure how to get the productDetail data here since it's a http request call.
}
]);
angular.module('App').factory('myFactory', function($http) {
var service = {};
service.request = function(id) {
return createProduct(id)
.then(function(obj) {
productID = obj.data.id;
return setProductDetail(productID)
})
.then(getDetail)
.then(function(productDetail) {
return productDetail.data
})
}
var createProduct = function(id) {
return $http.post('/api/product/create', id)
}
var setProductDetail = function(id) {
return $http.post('/api/product/setDetail', id)
}
var getDetail = function() {
return $http.get('/api/product/getDetail')
}
return service;
});
I was able to get the request result for my parentCtrl but I am not sure how to pass it to my child controller. Can anyone help me about it?
Thanks!
Potential approaches:
1) Inject myFactory into the child controller as well.
2) Access the parent scope directly from within childCtrl:
$scope.$parent.productDetail
3) If wanting to access from HTML
$parent.productDetail
Above assumes you are wanting to access that value specifically separate from a potential version on the child scope (existing code doesn't show that).
If it's a child scope, and nothing on the child scope (or a scope in between) is named productDetail, and you're not setting a primitive value in the child scope with that name, then you should be able to see the value directly through prototypical inheritance (but any of the three scenarios listed could force the need for a reference through the parent).

Updating angular.js service object without extend/copy possible?

I have 2 services and would like to update a variable in the 1st service from the 2nd service.
In a controller, I am setting a scope variable to the getter of the 1st service.
The problem is, the view attached to the controller doesn't update when the service variable changes UNLESS I use angular.extend/copy. It seems like I should just be able to set selectedBuilding below without having to use extend/copy. Am I doing something wrong, or is this how you have to do it?
controller
app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
$scope.building = BuildingsService.getSelectedBuilding();
});
service 1
app.factory('BuildingsService', function() {
var buildingsList = [];
var selectedBuilding = {};
// buildingsList populated up here
...
var setSelectedBuilding = function(buildingId) {
angular.extend(selectedBuilding, _.find(
buildingsList, {'building_id': buildingId})
);
};
var getSelectedBuilding = function() {
return selectedBuilding;
};
...
return {
setSelectedBuilding: setSelectedBuilding,
getSelectedBuilding: getSelectedBuilding
}
});
service 2
app.factory('AnotherService', function(BuildingsService) {
...
// something happens, gives me a building id
BuildingsService.setSelectedBuilding(building_id);
...
});
Thanks in advance!
When you execute this code:
$scope.building = BuildingsService.getSelectedBuilding();
$scope.building is copied a reference to the same object in memory as your service's selectedBuilding. When you assign another object to selectedBuilding, the $scope.building still references to the old object. That's why the view is not updated and you have to use angular.copy/extend.
You could try the following solution to avoid this problem if you need to assign new objects to your selectedBuilding:
app.factory('BuildingsService', function() {
var buildingsList = [];
var building = { //create another object to **hang** the reference
selectedBuilding : {}
}
// buildingsList populated up here
...
var setSelectedBuilding = function(buildingId) {
//just assign a new object to building.selectedBuilding
};
var getSelectedBuilding = function() {
return building; //return the building instead of selectedBuilding
};
...
return {
setSelectedBuilding: setSelectedBuilding,
getSelectedBuilding: getSelectedBuilding
}
});
With this solution, you have to update your views to replace $scope.building bindings to $scope.building.selectedBuilding.
In my opinion, I will stick to angular.copy/extend to avoid this unnecessary complexity.
I dont believe you need an extend in your service. You should be able to watch the service directly and respond to the changes:
app.controller('SelectedBuildingCtrl', function($scope, BuildingsService) {
// first function is evaluated on every $digest cycle
$scope.$watch(function(scope){
return BuildingsService.getSelectedBuilding();
// second function is a callback that provides the changes
}, function(newVal, oldVal, scope) {
scope.building = newVal;
}
});
More on $watch: https://code.angularjs.org/1.2.16/docs/api/ng/type/$rootScope.Scope

Categories

Resources