AngularJS - using a Resolve to pass data to a modal - javascript

Title says it all. I created a modal and I want data to pass to the modal from another page.
Here is the button that opens the open the modal. (rollup.html)
<button id="myBtn" ng-click="printDivModal('rollup-tab', test)">Modal Test</button>
Here I setup up the controller and the resolve (rollup.js)
app.controller('Rollup', function($scope, $rootScope, $http, $uibModal, headersvc, locFiltersvc) {
$scope.printDivModal = function(divName,test) {
console.log('opening pop up');
var ModalInstance = $uibModal.open({
scope: $scope,
animation: $scope.animationsEnabled,
templateUrl: 'app/views/modals/stackedModal.html',
size: 'xl',
controller: 'PrintViewCtrl',
backdrop : 'true',
resolve: {
test: function () {
return test;
}
}
});
}
});
app.controller('PrintViewCtrl', function($scope, $http, $rootScope, $uibModalInstance) {
$scope.test = function() {
$scope.regionName;
$scope.groupName;
$scope.mcName;
$scope.districtNumber;
$scope.routeNumber;
$scope.weekEndDate;
};
});
I am not sure if I need to put this in the modal-body (stackedModal.html), or if clicking the button will pass 'test'.
<div class="modal-body">
<p>{{test.regionName}}</p>
</div>
The data I want to pass to the modal is all within Route.html. Here is apart of the page.
<div class="row">
<div class="col-xs-6 col-md-4">
<label>Region:</label>
<span>{{regionName}}</span>
</div>
<div class="col-xs-6 col-md-4">
<label>Group:</label>
<span>{{groupName}}</span>
</div>
<div class="col-xs-6 col-md-4">
<label>MC:</label>
<span>{{mcName}}</span>
</div>
<div class="col-xs-6 col-md-4">
<label>District #:</label>
<span>{{districtNumber}}</span>
</div>
<div class="col-xs-6 col-md-4">
<label>Route #:</label>
<span>{{routeNumber}}</span>
</div>
<div class="col-xs-6 col-md-4">
<label>Week Ending Date:</label>
<span>{{weekEndDate}}</span>
</div>
<div class="col-xs-6 col-md-4">
<label>RSR:</label>
<span style="text-transform: capitalize;">{{rsrName}}</span>
</div>
</div>
Any suggestions to help me accomplish this? I am new this angular js. Thanks!
UPDATE
Printing the data with color and organized V
This is what opens the new tab when you click the printerFriendly button. (rollup.js)
app.controller('Rollup', function($scope, $rootScope, $http, $uibModal, headersvc, locFiltersvc) {
$scope.printDiv = function(divName) {
var topWrapper = "<div class='panel panel-default'><div class='panel-body'>";
var bottomWrapper="</div></div>";
var printContents = document.getElementById(divName).innerHTML;
var links = $(document).find('link');
var scripts = $(document).find('script')
var styles = "";
for (var i = 0; i < links.length; i++) {
styles += links[i].outerHTML;
}
var popupWin = window.open('', '_blank');
popupWin.document.open();
popupWin.document.write('<html><head>' + styles + '</head><body>' + printContents + '</body></html>');
}
}
I want the print preview to contain the color as seen in the main table

You should have a variable 'test' in the dependencies of PrintViewCtrl.
app.controller('PrintViewCtrl', function($scope, $http, $rootScope, $uibModalInstance, test)
Moreover you must have a test variable in the $scope of the "Rollup" controller. When you set "printDivModal('rollup-tab', test)" for the click, printDivModal and test are searched in the scope.
EDIT
test can be an object like
$scope.test = {regionName:..., mcName:..., etc...}
And then in your html use
{{test.regionName}} instead of {{regionName}}
for example.

Related

How to hide-show a modal only in one resolution?

Have two component. The first have an ng-click and call the modal with the second component, everything works fine. What the problem is the modal should only be opened in 768 resolution...
Already try with media queries but no success..
Thanks!
here is code:
parent.html:
<div class="col-xs-12 col-sm-12 col-md-12 col-lg-12" ng-click="$ctrl.openModal()">
<div class="col-xs-12 col-sm-9 col-md-9 col-lg-9 benefit-parenthood">
<div class="description">
<p class='title'>lorem impsun title</p>
<p class="area">
<i class="fa fa-cookie-bite cookie-icon" aria-hidden="true"></i>
<span class="area-item">lorem impsum</span>
</p>
<p class="area-mobile">lalala</p>
</div>
</div>
<div class="hidden-xs col-sm-3 col-md-3 col-lg-3 container-image">
<div class="partner-brand">
<img src="app/assets/greyimg.png" class="partner-avatar">
</div>
</div>
</div>
parent.component.js :
(function () {
'use strict';
angular
.module('parenthoodBenefit')
.component('parenthoodBenefitComponent', {
bindings: {},
templateUrl: 'app/parenthood-benefit/parenthood.html',
controller: parenthoodBenefitCtrl
})
function parenthoodBenefitCtrl($scope, $uibModal) {
this.openModal = function () {
$uibModal.open({
templateUrl: 'app/modal-benefit/modal.html',
size: 'lg',
controller: function ($scope, $uibModalInstance) {
$scope.ok = function () {
$uibModalInstance.close();
};
$scope.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
}
}).result.then(function () { }, function (res) { })
};
}
}());
modal.html :
<i class="fa fa-times icon-close" aria-hidden="true" ng-click="ok()" ></i>
<access-detail-component></access-detail-component>
Inside this.openModal() method check if( $(window).width() > 767 ) { open modal.....}
1.Get the width of window as you did and simply disable the click
In Controller
$scope.width=$window.innerWidth <= 768? false: true;
2.In html add ng-disabled="width" to respective div
This may better approach
1.Updated answer - Add below function in your controller
- This will get updated width if width changes
angular.element($window).bind('resize', function(){
if($window.innerWidth <= 768){
$scope.width =false;
}else{
//to disable click of open modal
$scope.width =true;
//then close your modal forcefully
$uibModalInstance.close();
//Run digest
$scope.$digest();
});
2.In html add ng-disabled="width" to respective div

how to use same component twice in angular Js html page [duplicate]

I'm creating a set of widgets with AngularJS 1.5's new components. The problem is, when using the same widget multiple times, they somehow share their controller or scope. I thought one of the things about components was that their scope is completely isolated?
My main html template which hold the widgets:
<widget-list
title="Books"
class="col-xs-12 col-md-4">
</widget-list>
<widget-list
title="Movies"
class="col-xs-12 col-md-4">
</widget-list>
<widget-list
title="Albums"
class="col-xs-12 col-md-4">
</widget-list>
My widget template:
<div class="widget widget-list">
<div class="panel b-a">
<div class="panel-heading b-b b-light">
<h5>{{$widget.title}}</h5>
<div class="pull-right">
<button type="button" class="btn btn-default btn-sm" ng-click="$widget.doSomething()">
Do something
</button>
</div>
</div>
<div class="panel-content">
{{$widget.content || 'No content'}}
</div>
</div>
</div>
My widget component:
app.component('widgetList', {
templateUrl: 'template/widget/widget-list.html',
bindings: {
title : '#',
},
controllerAs: '$widget',
controller: function($timeout) {
$widget = this;
console.log('Title on init: ', $widget.title)
$timeout(function() {
console.log('Title after 3 seconds: ', $widget.title)
}, 3000)
$widget.doSomething = function() {
$widget.content = "Something";
}
}
});
When running my code, this is what my console looks like:
Title on init: Books
Title on init: Movies
Title on init: Albums
(3) Title after 3 seconds: Albums
Also after rendering, all three widgets display No content in their template. But, when clicking the doSomething() button in either one of the three widgets, only the content of the last widget updates to Something.
What is happening here? Why are my components not 'isolated'?
Looks like you have a global variable called $widget here, try this:
var $widget = this;
instead of
$widget = this;
It creates a mess since the $widget variable holds a reference to the controller that has been recently initialized, in this case to the controller of the third component.
The problem with your code is that you are declaring the $widget on window scope, that's why your controller prints the last value, bacause it was being overridden every time the controller was getting instantiated. Use a var $widget instead and your code will work fine.
The following snippet solves this issue:
angular.module('app', [])
.component('widgetList', {
templateUrl: 'template/widget/widget-list.html',
bindings: {
title: '#',
},
controllerAs: '$widget',
controller: WidgetListController
});
function WidgetListController($timeout) {
var $widget = this;
console.log('Title on init: ', $widget.title)
$timeout(function() {
console.log('Title after 3 seconds: ', $widget.title)
}, 3000)
$widget.doSomething = function() {
$widget.content = "Something";
}
}
angular.element(document).ready(function() {
angular.bootstrap(document, ['app']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.min.js"></script>
<widget-list title="Books" class="col-xs-12 col-md-4">
</widget-list>
<widget-list title="Movies" class="col-xs-12 col-md-4">
</widget-list>
<widget-list title="Albums" class="col-xs-12 col-md-4">
</widget-list>
<script type="text/ng-template" id="template/widget/widget-list.html">
<div class="widget widget-list">
<div class="panel b-a">
<div class="panel-heading b-b b-light">
<h5>{{$widget.title}}</h5>
<div class="pull-right">
<button type="button" class="btn btn-default btn-sm" ng-click="$widget.doSomething()">
Do something
</button>
</div>
</div>
<div class="panel-content">
{{$widget.content || 'No content'}}
</div>
</div>
</div>
</script>

angularJS $watch do not work in directive when use controller to update data

I have a custom directive,and also have a controller to bind the data to directive.
I get the data from the server part and bind it to directive.However,I found the data of directive on page do not update when I change scope variable
Here is my code
directive:
angular.module('MyApp')
.directive('stats',function() {
return {
templateUrl:'scripts/directives/dashboard/stats/stats.html',
restrict:'E',
replace:true,
scope: {
'comments': '#',
'number': '#',
'name': '#',
'colour': '#',
'details':'#',
'type':'#',
'goto':'#'
},
link : function($scope,element,attr){
$scope.$watch('number', function(oldValue,newValue) {
console.log(attr);
}, true);
}
}
});
directive template:
<div class="col-lg-3 col-md-6">
<div class="panel panel-{{colour}}">
<div class="panel-heading">
<div class="row">
<div class="col-xs-3">
<i class="fa fa-{{type}} fa-5x"></i>
</div>
<div class="col-xs-9 text-right">
<div class="huge">{{number}}</div>
<div>{{comments}}</div>
</div>
</div>
</div>
<a href="{{goto}}">
<div class="panel-footer">
<span class="pull-left">查看详情</span>
<span class="pull-right"><i class="fa fa-arrow-circle-right"></i></span>
<div class="clearfix"></div>
</div>
</a>
</div>
controller:
'use strict';
angular.module('MyApp',['ngResource'])
.controller('MainCtrl', function($scope,$state,MyService) {
$scope.result = {};
var names = MyService.get({classtype:'getNames',start:'',end:''},function(){
$scope.pages = names.data;
if (typeof($scope.pages[0]) === 'undefined'){
$scope.selectedItem = 'loading...';
}else{
$scope.selectedItem = $scope.pages[0].name;
}
var res = MyService.get({classtype:'getLastRes',seriesName:$scope.selectedItem},function(){
$scope.result = res;
});
});
$scope.dropboxitemselected = function(item){
$scope.selectedItem = item;
var result = MyService.get({classtype:'getLastRes',seriesName:item},function(){
$scope.result = result;
});
//$scope.result = {};
};
});
HTML:
<div class="row" ng-controller="MainCtrl">
<stats number="{{result.score}}" comments="score" colour="primary" type="heartbeat" goto="#/res/{{result._id}}"></stats>
<stats number="{{result.totalSize}}" comments="size" colour="primary" type="file-code-o" goto="#/res/{{result._id}}"></stats>
<stats number="{{result.count}}" comments="count" colour="red" type="file-text" goto="#/res/{{result._id}}"></stats>
</div>
there is a dropdown box on my page,I need refresh data in directive when I change item by function dropboxitemselected in controller,How can I do?
I think it is because of the scope bindings, you should use '=' for two way binding instead of '#'.
scope: {
'number': '=',
},
And in your HTML remove the brackets from number.
<stats number="result.score" comments="score" colour="primary" type="heartbeat" goto="#/res/{{result._id}}"></stats>

Angular directive stops working after being moved from one DOM element to another

I have a modal service in my app that opens/closes a modal. When the modal is opened, it plucks its content from the div with the specified id, which always sits inside a container elem that is hidden. Normally this works fine.
The problem I'm having now is that when a user opens the modal with the mediaBrowser directive for the first time, they can navigate between the photos/videos tab and select an item to attach to a post. If the modal is closed and reopened though, nothing works. The photos load as expected, but clicking one does nothing. It's as if none of the functions in the mediaBrowser or mediaBrowserPhotos directive work.
I thought it might have something to do with needing to compile the directive after its moved from one DOM element to another, but I've not had much luck resolving it with the $compile service.
Here is my modal service:
app.service('modal', [function() {
var modal = this;
modal.settings = {};
modal.overlay = $('<div id="overlay"></div>');
modal.modal = $('<div id="modal"></div>');
modal.content = $('<div id="content"></div>');
modal.closeBtn = $('<div id="close"><i class="fa fa-times"></div>');
modal.modal.hide();
modal.overlay.hide();
modal.modal.append(modal.content, modal.closeBtn);
$(document).ready(function(){
$('body').append(modal.overlay, modal.modal);
});
modal.open = function (settings) {
modal.settings = settings;
var content = modal.settings.content;
modal.content.empty().append(content);
if(modal.settings.class) modal.modal.addClass(modal.settings.class);
if(modal.settings.height) modal.modal.css({ height: settings.height });
if(modal.settings.width) modal.modal.css({ width: settings.width });
if(modal.settings.content_height) modal.modal.css({ height: settings.content_height });
if(modal.settings.content_width) modal.modal.css({ width: settings.content_width });
if(modal.settings.fitToWindow) {
modal.settings.width = $(window).width() - 160;
modal.settings.height = $(window).height() - 160;
};
center(modal.settings.top);
$(window).bind('resize.modal', center);
modal.modal.show();
modal.overlay.show();
$(modal.closeBtn).add(modal.overlay).on('click', function(e) {
e.stopPropagation();
modal.close();
});
$(document).on('keyup', function(e) {
if (e.keyCode == 27) {
modal.close();
$(document).unbind('keyup');
}
})
};
modal.close = function() {
var elem = modal.settings.elem;
var content = modal.settings.content;
elem.empty().append(content);
modal.modal.hide();
modal.overlay.hide();
modal.content.empty();
$(window).unbind('resize.modal');
};
function center(top) {
if(!top || !isInt(top)) top = 130;
var mLeft = -1 * modal.modal.width() / 2;
modal.modal.css({
top: top + 'px',
left: '50%',
marginLeft: mLeft
});
function isInt(n) {
return n % 1 === 0;
}
}
}]);
I also have a mediaBrowser directive in my app, which housed 2 child directives representing a photos and videos tab. Here is my mediaBrowser directive:
app.directive('mediaBrowser', ['$rootScope', 'profileAPI', 'photosAPI', 'videosAPI', function($rootScope, profileAPI, photosAPI, videosAPI) {
return {
replace: true,
templateUrl: '/assets/employers/media_browser.html',
scope: {
model: '=',
card: '=',
type: '=',
photoContainer: '=',
videoContainer: '=',
mediaBrowserContainer: '=',
mediaBrowserForm: '='
}, controller: ['$scope', '$rootScope', 'profileAPI', 'photosAPI', 'videosAPI', function($scope, $rootScope, profileAPI, photosAPI, videosAPI) {
$scope.mediaView = profileAPI.mediaView;
resize($scope.mediaView);
$rootScope.$on('mService:keyChanged', function resultsUpdated(event, value) {
$scope.mediaView = profileAPI.mediaView;
resize($scope.mediaView);
});
$scope.setMediaView = function(view) {
profileAPI.mediaView = view;
};
function resize(resource) {
if(resource === 'photos') {
photosAPI.resizeColumns('#media_browser_photos_new_' + $scope.type);
} else if (resource === 'videos') {
videosAPI.resizeColumns('#media_browser_videos_new_' + $scope.type);
}
}
}]
}
}]);
Here is the partial for the mediaBrowser directive:
<div style="display:none" id="{{mediaBrowserContainer}}">
<div id="{{mediaBrowserForm}}">
<div class="row">
<div class="col-lg-12">
<div class="row subheader modal-tabs">
<ul class="nav navbar-nav">
<li ng-class="{'active-sub': mediaView === 'photos'}">
<a ng-click="setMediaView('photos');">Photos</a>
</li>
<li ng-class="{'active-sub': mediaView === 'videos'}">
<a ng-click="setMediaView('videos');">Videos</a>
</li>
</ul>
</div>
</div>
</div>
<div class="row" ng-if="mediaView === 'photos'">
<div media-browser-photos
model="model"
container="photoContainer"
media-browser-container="mediaBrowserContainer"
media-browser-form="mediaBrowserForm"
for-type="type"
mode="'new'">
</div>
</div>
<div class="row" ng-if="mediaView === 'videos'">
<div media-browser-videos
model="model"
container="videoContainer"
media-browser-container="mediaBrowserContainer"
media-browser-form="mediaBrowser"
for-type="type"
mode="'new'">
</div>
</div>
</div>
</div>
Here is my mediaBrowserPhotos directive. Note that the videos version is basically identical to photos:
app.directive('mediaBrowserPhotos', ['$rootScope', '$timeout', '$q', 'photosAPI', 'modal', function($rootScope, $timeout, $q, photosAPI, modal) {
return {
replace: true,
templateUrl: '/assets/employers/media_browser_photos.html',
scope: {
container: '=',
model: '=',
mediaBrowserContainer: '=',
mediaBrowserForm: '=',
forType: '=',
mode: '='
}, controller: ['$scope', '$rootScope', '$timeout', '$q', 'photosAPI', 'modal', function($scope, $rootScope, $timeout, $q, photosAPI, modal) {
$scope.current_page = photosAPI.current_page;
$scope.results = [];
$scope.loading = false;
$scope.num_pages = 0;
$scope.page_numbers = photosAPI.page_numbers;
$scope.total_count = 0;
$scope.count = 0;
$scope.order = false;
var thumbSize = 150;
var q = $scope.current_page;
$rootScope.$on('cService:keyChanged', function resultsUpdated(event, value) {
$scope.results = photosAPI.results;
$scope.loading = photosAPI.loading;
$scope.num_pages = photosAPI.num_pages;
$scope.page_numbers = photosAPI.page_numbers;
$scope.total_count = photosAPI.total_count;
});
$scope.selectMedia = function(options) {
if($scope.mode === 'new') {
var content = '#add_card_form';
var elem = '#add_card_form_container';
} else {
var content = '#' + $scope.forType + '_' + $scope.model.id + '_form';
var elem = '#' + $scope.forType + '_' + $scope.model.id + '_form_container';
};
$scope.model[options.type] = options.object;
modal.close();
modal.open({
content: $(content),
elem: $(elem),
height: '594px',
content_height: '578px'
})
}
}]
}
}]);
Here is the partial for mediaBrowserPhotos:
<div class="column-layout cols-3 search-results-no-resize" id="{{container}}">
<div class="multiple-photo-upload media">
<button type="button" class="btn btn-default dropdown-toggle" ng-click="orderAsc();">
Sort by Date
Oldest First <i class="fa fa-arrow-up" style="font-size: 1.3em;"></i>
Newest First <i class="fa fa-arrow-down" style="font-size: 1.3em;"></i>
</button>
<div class="paginator" ng-if="page_numbers.length > 1">
<div class="page-btn prv" ng-click="prevPage()"><i class="fa fa-chevron-left"></i></div>
<div class="page-btn" ng-repeat="p in page_numbers" ng-class="{'current':p === current_page}" ng-click="loadPage(p)">{{p}}</div>
<div class="page-btn nxt" ng-click="nextPage()"><i class="fa fa-chevron-right"></i></div>
</div>
</div>
<div class="results-label media"><b>{{total_count}}</b> <span ng-if="total_count == 1">Photo</span><span ng-if="total_count != 1">Photos</span></div>
<div class="media-browser photos" ng-show="!loading && total_count > 0">
<div class="col">
<div ng-repeat="r in results" class="card result-link">
<div class="content result">
<div class="image-container" ng-style="{'background-image': 'url(' + r.image_url + ')'}" ng-click="$parent.selectMedia({object: r, type: 'image'})"></div>
</div>
</div>
</div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<div class="col" style="display:none"></div>
<br style="clear:both" />
</div>
<div ng-show="loading" class="loading-results">
<i class="fa fa-spinner fa-spin"></i>
</div>
</div>
The whole app itself is pretty complex and difficult to reproduce in a Plucker/Fiddle. Any help would be greatly appreciated. Let me know of you need any additional code from the app!
Try this: instead of moving the whole thing, wrap it in another element, leave that one in place and move the same element you were moving now (now the child of the element in your link function).
If you don't use replace:true, which is deprecated anyway, you get that element for free (the directive's element).
Good luck!

angular how to reload a controller

I have a categoriesPanel controller that on ng-click I want to show all the products belongings to that category inside my ng-controller productsPanel. The problem im having is that every time I click on the ng-click="selectorCategory" I get the all the products in the clicked category after I refresh the page.
<div class="col-md-6 m-t-10" ng-controller="productsPanel" style="padding-right:1px;">
<div class="panel panel-default" style="height: 700px">
<div class="panel-body">
<div ng-repeat="product in Products" class="productRow">
{{product.Product}}
</div>
</div>
</div>
</div>
<div class="col-md-3 m-t-10" ng-controller="categoriesPanel" style="padding-left: 0; padding-right: 5px">
<div class="panel panel-default" style="height: 700px">
<div class="panel-body">
<div ng-repeat="category in Categories" class="categoryRow">
{{category.Category}}
</div>
</div>
</div>
</div>
this is my angular script that is getting the right data from the backend but the data only shows in the producsPanel controller when i refresh the page. I want to data to show as soon as you do the ng-click.
app.controller('categoriesPanel', function($scope, $location, $http, $localStorage){
var CompanyId = $localStorage.Employee[0].CompanyId;
$http({
method : 'GET',
url : 'http://localhost:8888/categories/ajax_getCompaniesCategories',
params: {CompanyId: CompanyId}
})
.success(function(data){
$scope.Categories = data;
$localStorage.Categories = data;
});
$scope.selectedCategory = function(event){
$localStorage.CategoryId = $(event.target).data('id');
$http({
method : 'GET',
url : 'http://localhost:8888/products/ajax_getCategoryProducts',
params: {CategoryId: $localStorage.CategoryId}
})
.success(function(data){
$scope.Products = data;
$localStorage.Products = data;
});
}
});
app.controller('productsPanel', function($scope, $location, $http, $localStorage){
$scope.Products = $localStorage.Products;
});
/* END CONTROLLERS */
Maybe the product array you are pointing to gets clear when call to getcategoryproducts is made. Can you fix your callback for ajax_getCategoryProducts and change success to push elements into the array instead of reassignment.
.success(function(data){
$scope.Products.length=0;
data.forEach(function(p) {
$scope.Products.push(p);
});
$localStorage.Products = $scope.Products;
});

Categories

Resources