i have two controllers, the data in the first controller will be updated by click functions in the second controller. I am using service to communicate between controllers and not getting the expected result. whats wrong i am doing
link: http://jsbin.com/hozabigedu/1/
Well, you had several issues. First, I changed your data to be an object and to have a boolean as a property, rather than have itself be a boolean. This is good practice if you want to share info using a service. It's better that you share an object so that different controllers share the same reference. Primitives are problematic for that scenario. So here's the new service:
app.service('testservice', function(){
var data={}; //Changed here
getDataText = function() {
return data;
};
setDataText= function(val) {
data.text = val; //And changed here
return data;
};
return {
getDataText: getDataText,
setDataText: setDataText
};
});
Another issue is that your controller called the wrong function, it should be getDataText():
$scope.inputText = testservice.getDataText();
And lastly, you forgot to close the divs of the click elements, so the click 2 events bubbled up to the click 1 events thus showing right after hiding, so replace the 2nd controller div with this one:
<div ng-controller="secondController">
<div ng-click="showDiv();">click1</div>
<br/>
<br/>
<div ng-click="hideDiv();">click2</div>
</div>
</div>
Related
I'm new in angular and i'm looking for the best way to do what I want.
In my main page I have 2 directives, one is used to display a button (and maybe other stuff). And another used to display a kind of dialog box/menu.
Each directive has its own controller.
I want to show or hide the second directive when I click on the button in the first one.
I don't really know what are goods or wrong approaches. Should I use a service injected in both controller and set a variable with ng-show in the second directive? This solution doesn't really hide the directive because I need a div inside the directive to hide its content and isn't too much to use a service only for one boolean?
Should I use a kind of global variable (rootscope?) or inject the first controller inside the second one?
Or maybe use a third controller in my main page (used with a service?) or use only one controller for both directive?
Basically without directive I would probably used only one main controller for my whole page and set a variable.
In fact the first directive is just a kind of button used to display "something", and the second directive just a kind of popup waiting a boolean to be displayed. That's why I finally used a service containing a boolean with a getter and a setter to avoid any interaction beetween both controller.
My both controller use this service, the first one to set the value when we click on the element and the second controller provide just a visibility on the getter for my ng-show.
I don't know if it is the best way to do but I am satisfied for now.
Small example here (without directive but with same logic) :
http://codepen.io/dufaux/pen/dXMrPm
angular.module('myModule', []);
angular.module("myModule")
.controller("ButtonCtrl", buttonCtrl)
.controller("PopUpCtrl", popUpCtrl)
.service("DisplayerService", displayerService);
//ButtonCtrl
buttonCtrl.$inject = ["DisplayerService", "$scope"];
function buttonCtrl(DisplayerService, $scope) {
var vm = this;
vm.display = function(){
DisplayerService.setDisplay(!DisplayerService.getDisplay());
}
}
//PopUpCtrl
popUpCtrl.$inject = ["DisplayerService"];
function popUpCtrl(DisplayerService) {
var vm = this;
vm.displayable = function(){
return DisplayerService.getDisplay();
}
}
//Service
function displayerService(){
var vm = this;
vm.display = false;
vm.setDisplay = function(value){
vm.display = value;
}
vm.getDisplay = function(){
return vm.display;
}
}
--
<body data-ng-app="myModule">
<div data-ng-controller="ButtonCtrl as btnCtrl" >
<button data-ng-click="btnCtrl.display()">
display
</button>
</div>
[...]
<div data-ng-controller="PopUpCtrl as popUpCtrl" >
<div data-ng-show="popUpCtrl.displayable()">
hello world
</div>
</div>
</body>
So, I have a ng-repeated list of items as such.
<li><a ng-click="{{person.id}}">Name of Person</a></li>
I would like to create a service wherein, on click, I can collect that person.id and pass it to another controller in a different route.
This would normally be very simple by just using the url and route params, however, in this case it is important that the person.id not be exposed within the browser url.
-- More Context
Whether service or not, I am needing to extract a {{person.Id}} that is data available via an ng-repeat on a list page of persons.
On click, I move from a persons controller to a new route with a "person" controller. I need that "person" controller to be able to pull the {{Person.ID}} that was clicked on the previous route in order to look up that person in a DB.
Any help would be really great!
Services aren't meant to interact directly with DOM elements. DOM should interact with directives/controllers. Controller should interact with models.
This example below demonstrates sending data from controller 1 to myFactory and then controller 2 gets it the value from myFactory.
angular
.module('app', [])
.factory('myFactory', myFactory)
.controller('myCtrl1', myCtrl1)
.controller('myCtrl2', myCtrl2);
function myFactory() {
var fromSender = null;
return {
setSender: function(sender) {
fromSender = sender;
},
getSender: function() {
return fromSender;
}
};
}
function myCtrl1(myFactory) {
var vm = this;
vm.setSender = myFactory.setSender;
}
function myCtrl2(myFactory) {
var vm = this;
vm.getSender = myFactory.getSender;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="app">
<div ng-controller="myCtrl1 as ctrl1">
Controller 1: <br>
<button ng-click="ctrl1.setSender('from controller 1')">Send to myFactory</button>
</div>
<hr>
<div ng-controller="myCtrl2 as ctrl2">
Controller 2: <br>
value from ctrl1 via myFactory: {{ctrl2.getSender()}}
</div>
</div>
All services in Angular are singletons. So if you inject personService or something like that, in multiple controllers, then those controllers will be using the exact same object. So if you set a value on that service, then the other controllers will be able to see it.
With more code and context, I'll be able to give a more specific example.
I am working on an MVC application using Angular. I need to open various bootstrap modal in one of the application pages. for that i just wrote a simple angular service to get the template for modal from a folder called templates and load at Run-time. Everything works fine except one thing. ng-model is not working for check box controls and DropDownList(select) items.
service to load template:
var defaultPath = "/app/services/dialog/templates/";
function _loadModalTemplate(templateName) {
var defer = $q.defer();
if (angular.isUndefined($templateCache.get(templateName))) {
return $http.get(defaultPath + templateName).then(function (data) {
$templateCache.put(templateName, data.data);
return defer.resolve();
});
} else {
return $.when($templateCache.get(templateName));
}
return defer.promise;
}
Controller
notebook.controller('createworkitemcontroller', ['$scope', '$modalInstance', 'workitemDataContext', 'common', 'options',
function ($scope, $modalInstance, workitemDataContext, common, options) {
$scope.activities = options.activities || [];
$scope.activity = $scope.activities[0];
}]);
Template HTML
<div class="col-lg-6">
<label class="text-xs">Activity</label>
<select class="form-control input-sm" data-ng-options="a.Name for a in activities" data-ng-model="activity"></select>
</div>
Data Binding is working fine but its not updating the property $scope.activity when any change is made. Same case with checkboxes as well but working with TextBox
I'm wondering if the assignment is breaking the chain of scope. Try adding your variables inside a dedicated object like $scope.model = {activity: ...} and see if it works. I ran into this when I started using multiple modals and controllers. Here's a fiddle I made a while back demonstrating the concept:
http://jsfiddle.net/6XDtN/
http://jsfiddle.net/6XDtN/1/
In the first one, the parent is oblivious because the child re-defined the variable, breaking the chain of scope. It isn't obvious it re-defined the variable, but there's no way to really re-assign a value without doing so.
In the second one, the complex type (i.e. an object), is not redefined, just a property is updated. Thus, the chain of scope is strong in this one.
Hope this helps!
I have 2 modals that use the same controller. One has:
<div id="addToPlaylist" ng-controller="PlaylistModalCtrl">
<select name="playlist" ng-model="playlist" ng-options="playlist.id as playlist.name|rmExt for playlist in playlists">
</select>
The other has:
<div id="newPlaylist" ng-controller="PlaylistModalCtrl">
<button ng-click="createPlaylist(playlistName);">Save</button>
In my controller, I have:
angular.module('MyApp')
.controller('PlaylistModalCtrl', function ($scope) {
$scope.playlists = [];
$scope.updatePlaylists = function() {
getPlaylist.then(function (response) {
$scope.playlists = response.data.data;
$scope.$$phase || $scope.$apply();
});
}
$scope.createPlaylist = function(playlist_name) {
addPlaylist(playlist_name).then(function(response) {
$("#newPlaylist").modal('hide');
});
}
$scope.updatePlaylists();
});
So one would expect that my first view would have an updated "playlists" in the dropdown, but this isn't the case. So how can I get that view to be updated?
You don't seem to understand how scoping works. Here is a plunkr illustrating that two different controllers have different scopes and stuff.
http://plnkr.co/edit/LqLuLvVkE9ltzcJH6XdN?p=preview
As you can clearly see, expecting two controllers to update the same variable would not work because each of them has the variable in its own isolated scope. What you can do to battle that is to implement a pubsub service that listens to some changes for some properties, use emit and broadcast angular functions, or, the best, rethink why you would need the same controller twice in your app and redesign it.
I like that AngularJS doesn't require and special syntax for Models, but there's one scenario I can't seem to wrap my head around. Take the following
My dataService wraps whatever flavor of data storage I'm using:
app.factory('dataService', function() {
var data = 'Foo Bar';
return {
getData: function() {
return data;
}
};
});
I have two controllers that both access the same piece of data:
app.controller('display', function($scope, dataService) {
$scope.data = dataService.getData();
});
app.controller('editor', function($scope, dataService) {
$scope.data = dataService.getData();
});
If I then have two views, one of which modifies the data, why doesn't the other update automatically?
<div ng-controller="display">
<p>{{data}}</p>
</div>
<div ng-controller="editor">
<input type="text" value="{{data}}"/>
</div>
I understand how this is working in something like Knockout where I'd be forced to make the data a knockout observable object. So any modifications in one part of the application trigger subscriptions and update views in another. But I'm not sure how to go about it in Angular.
Any advice?
There are few changes that I would suggest to make it work.
change the data object from a string to object type
Use ng-model to bind the input field
HTML
<div ng-controller="display">
<p>{{data.message}}</p>
</div>
<div ng-controller="editor">
<input type="text" ng-model="data.message"/>
</div>
Script
app.factory('dataService', function() {
var data = {message: 'Foo Bar'};
return {
getData: function() {
return data;
}
};
});
Demo: Fiddle
I haven't been stuck with the same situation, but the thing that jumps out at me is what you are sticking in the scope. There was an angular video where scope was discussed. You should put model objects in the scope and not use the scope as your model object.
In your example two scopes will be created each with the string data. Since data is a string and immutable, it will be replaced in scope of editor when changed. In your example if you had dataService return an object and that object is shared between the controllers, then perhaps your problems would be resolved. Try having dataService return model of {data: data} and bind to model.data instead of data.
This is untested, but should work based on how I know angular works.