Reputation: 511
in this plunk I have made a demo for my problem which I'm facing from last week. Code snippet contains bootstrap tab which includes two different pages - page1 and page2 and they are using same controller. Page1 has ng-repeat and when we click on option from there then It's hit in controller function vm.edit(selected_variable) and Page2 has a simple input box that has a ng-model="vm.name". My problem is that ng-name is not updated or replaced with the value when vm.edit function updates it. I can solve this problem using rootScope but I don't want to use rootScope. I just want to avoid rootScope and want to use vm.
My code example:
page1:
<div ng-controller="appCtrl as vm">
<div>
<ul>
<li ng-repeat="list in vm.list track by $index">
<button type="button" class="btn-u btn-brd btn-u-none" ng-click="vm.edit(list, $index)" data-toggle="tab" href="#page2">
{{ list.name }}
</button>
</li>
</ul>
</div>
</div>
page2:
<div ng-controller="appCtrl as vm">
<input type="text" ng-model="vm.name">
</div>
Controller:
vm.edit = function(listItem, index) {
vm.name = listItem.name;
console.log(vm.name);
};
The edit function updates vm.name in page1 but it doesn't reflect in page2. Couldn't solve this issue, Any Ideas?
Upvotes: 2
Views: 195
Reputation: 1837
In order to communicate between controllers, you can make use of $broadcast event to transfer data. Here is the edited Plunker.
Inside vm.edit function register broadcast and listen to the event in the same controller:
vm.edit = function(listItem, index) {
$rootScope.$broadcast("vm name: changed", listItem.name);
};
$scope.$on("vm name: changed", function(evt, obj){
vm.name = obj;
});
Also don't forget to add $rootScope dependency to your controller:
app.controller('appCtrl', function($scope, $rootScope) {...});
Note: Here $rootScope is used only to trigger event but not to store the value.
Upvotes: 3
Reputation: 8324
You should just add two components, say the PageComponent and the PageContainerComponent. The PageContainerComponent is put in the masterpage that contains the tabs. The PageComponent requires the PageContainerComponent as a parent and contains the logic of the page.
Then you can simply put anything you want to share in the PageContainerComponent, since the PageComponent has access to it. If you can even bind things directly to the PageContainerComponent in the page views providing you make the PageContainerComponent available as a variable on the PageComponent.
Something like this:
angular.module('app').component('pageContainerComponent', {
controller: function() {
this.someProperty = 'yay';
},
template: '<div ng-transclude></div>'
});
angular.module('app').component('page1Component', {
controller: function() {
// This controller will now have a property tabsCtrl
// With the controller for pageContainerComponent
},
controllerAs: 'vm',
template: '<div>Page 1 content {{vm.tabsCtr.someProperty}}</div>',
require: {
tabsCtrl: '^myTabs'
},
});
Usage should be something like this
<page-container-component>
<div class="someTabClass">
<page1-component></page1-component>
</div>
</page-container-component>
This is all from the top of my head, so there may be a typo here or there, but I hope it helps anyway.
Edit
Oh, almost forgot, you can ofcourse use the same controller function for a page1Component and a page2Component, to make several pages with the same controller logic, but different views. I don't really see the point though, since the 'shared logic' should be in the pageContainerComponent anyway.
Upvotes: 0
Reputation: 486
page1.html
<div ng-controller="appCtrl">
<div>
<ul>
<li ng-repeat="listitem in list track by $index">
<button type="button" class="btn-u btn-brd btn-u-none" ng-click="edit(listitem, $index)" data-toggle="tab" href="#page2">
{{ listitem.name }}
</button>
</li>
</ul>
</div>
</div>
page2.html
<div ng-controller="appCtrl">
<div>
<ul>
<li ng-repeat="listitem in list track by $index">
<button type="button" class="btn-u btn-brd btn-u-none" ng-click="edit(listitem, $index)" data-toggle="tab" href="#page2">
{{ listitem.name }}
</button>
</li>
</ul>
</div>
</div>
script.js
var app = angular.module('app', []);
app.controller('appCtrl', function($scope, $compile) {
var vm = this;
// List
$scope.list = [
{
'id': 1,
'name': 'afroza'
},
{
'id': 2,
'name': 'yasmin'
}
];
// edit function
$scope.edit = function(listItem, index) {
$scope.name = listItem.name;
//this one is very important
$compile(angular.element( document.querySelector('#name')))($scope);
};
});
Upvotes: 1
Reputation: 971
page1 and page2 and they are using same controller
- they are not using same controller. They are using two different instances of same controller.
If you want to use same Controller instance, you can do ng-controller="appCtrl as vm"
on parent. Otherwise, you can use rootScope
or service
Upvotes: 0