$uibModal templateUrl does not change modal content - angularjs

all!
I'm making an angular application and want to implement a simple modal window popup, that will allow users to "construct" a URL.
My page looks like this:
Here's the HTML of the URL button (third in row) that is to trigger my button.
<button class="btn btn-secondary" ng-click="vm.showUrlModal()" id="button-url-to-modal" type="button" title="Hyperlink <a> Ctrl+L"><img src="/images/url.png" height="18px"/></button>
The controller that handles the page looks like this:
(function() {
function postchallengeController($uibModal, newChallengeData) {
var vm = this;
vm.message = "Post a challenge!";
vm.showUrlModal = function() {
$uibModal.open({
templateUrl: '/url_modal/url_modal.view.html',
controller: 'url_modal',
controllerAs: 'vm',
})
}
postchallengeController.$inject = ['$uibModal', 'newChallengeData'];
/* global angular */
angular
.module('stackunderflow')
.controller('postchallengeController', postchallengeController);
})();
And the referenced url_modal controller:
(function() {
function url_modal($uibModalInstance) {
var vm = this;
vm.modal = {
cancel: function() {
$uibModalInstance.close();
}
};
}
url_modal.$inject = ['$uibModalInstance'];
/* global angular */
angular
.module('stackunderflow')
.controller('url_modal', url_modal);
})();
In the referenced document (/url_modal/url_modal.view.html) is a simple Hello World, that should be displayed when I open the modal - however, when I do so, the page opens a modal with the current content overlayed on top of it.
See here :
What could I be doing wrong?
Thank you!
EDIT: I do have both controllers referenced in my index.html and my module does contain ['ui.bootstrap']

The error might be hidden in the reference of the html file.
Make sure that the parent directory of the /url_modal/ directory is set as the root folder you set with express.static function call.

Related

Ionic v1 global $ionicPopover menu

for my ionic v1 app I need to add one header menu (like as bootstrap menu) in right corner. When I click this button, i need to show menu with same ng-click event. For graphical requirement I need a menu and no side menu.
Found $ionicPopover, and I think that is my solution.
My problem is about menu function. My idea is use a html template for all menu, and put popover function samewhere accessibile for all my app. Is possibile?
Found only example where for every controller I need to implement popover function.
For example this is a simple controller. I need to define popover function globally for all my project. Same for popover definition. Is possible? Thanks.
.controller('DashCtrl', function($scope, $ionicLoading, $ionicPopover) {
// .fromTemplate() method
var template = '<ion-popover-view>' + '<ion-header-bar>' +
'<h1 class = "title">Popover Title</h1>' +
'</ion-header-bar>'+ '<ion-content>' +
'Popover Content!' + '</ion-content>' + '</ion-popover-view>';
$scope.popover = $ionicPopover.fromTemplate(template, {
scope: $scope
});
$scope.openPopover = function($event) {
$scope.popover.show($event);
};
$scope.closePopover = function() {
$scope.popover.hide();
};
//Cleanup the popover when we're done with it!
$scope.$on('$destroy', function() {
$scope.popover.remove();
});
// Execute action on hide popover
$scope.$on('popover.hidden', function() {
// Execute action
});
// Execute action on remove popover
$scope.$on('popover.removed', function() {
// Execute action
});
})
Like stated in my comment, you should create a root-template view with a separate Controller that holds the logic shared by all views. Take the following setup as an example:
The "Root Template": (Contains the Menu Button)
<!-- templates/root.html -->
<div>
<ion-nav-bar class="bar-positive">
<ion-nav-buttons side="right">
<button class="button icon ion-android-more-vertical" ng-click="showMenu($event)"></button>
</ion-nav-buttons>
</ion-nav-bar>
<ion-nav-view name="content"></ion-nav-view>
</div>
Dash Templates:
<!-- views/dash.html -->
<ion-view view-title="Dash View">
<ion-content>
Hello World!
</ion-content>
</ion-view>
The states:
$stateProvider
.state('root', {
url: '/root',
abstract: true,
templateUrl: 'templates/root.html',
controller: 'RootCtrl'
})
.state('root.dash', {
url: '/sub',
views: {
'content': {
controller: 'DashCtrl',
templateUrl: 'views/dash.html'
}
}
})
In the DashCtrl you will put your logic to handdle the popup. Thus this controller has to implement the showMenu($event) function.
If you really need a template for your popover, you can define the template in either in the html of templates/root.html or in the code of **RootController.js".
Finally, I create single function in single controller, with a common menu header. Thanks.
I know the OP resolved his issue but did it in a different way than was originally asked. The OQ was how to do a global popover...the accepted answer was to do controller view instead.
But to do a global popover, this is how I did it. I am certain some might object to this because of the dependency of $rootScope but it is a working solution:
In app.js:
var popoverPromise = $ionicPopover.fromTemplateUrl('templates/windowPopup.html', {
scope: $rootScope,
focusFirstInput:false
});
popoverPromise.then(function(popover) {
$rootScope.msgPopover = popover;
});
$rootScope.globalPopover = function(tpt,tps,tpm,tps1,tpm1,tpa,tpc) {
popoverPromise.then(function(popover) {
$rootScope.popInfo.title = tpt ;
$rootScope.popInfo.sub = tps ;
$rootScope.popInfo.msg = tpm ;
$rootScope.popInfo.sub1 = tps1;
$rootScope.popInfo.msg1 = tpm1 ;
$rootScope.popInfo.action = tpa ;
$rootScope.popInfo.color1 = tpc ;
$popover.show();
}) ;
}
$rootScope.globalClosePopover = function() {
$rootScope.msgPopover.hide();
}
And then from all the various controllers where you need it, inject $rootScope:
$rootScope.globalPopover(a,b,c,d,e,f,g) ;
An alternative to the above, if you don't need it everywhere - like in your app in init/register/startup controllers, is to put all this in your Tabs-Controller.

Open brand new $modal with Angular UI.Bootstrap every time

I'm using AngularJS with ui.bootstrap and have a modal directive, which works fine.
myApp.directive("modalButton", ['$uibModal', function ($uibModal) {
return {
restrict: "A",
scope: {
modalUrl: '#',
modalModel: '='
},
link: function (scope, element, attrs) {
element.bind('click', function () {
var modalInstance = $uibModal.open({
templateUrl: scope.modalUrl, // Here I want to use an url instead.
controller: 'editDeliveryCtrl as ctrl',
resolve: {
model: function () {
return scope.modalModel;
}
}
});
});
}
};
}]);
And used like:
<button type="button" class="btn btn-xs btn-default" modal-model="ctrl.currentDelivery" modal-button modal-url="#Url.Action("AddDelivery", "ProvisionContract", new {provisionContractId = Model.Id})">
<span class="fa fa-plus" area-hidden="true"></span>
</button>
When a user clicks on a button with the directive a modal is shown. However, I'm using MVC.Net and the modals I'm loading is often a form with #Html.AntiForgeryToken() or other code-behind logic. So what I really want is to reload the template every time (make a new request to the server).
I've read question below and that may be a good answer, but what I really want is to not use templates at all. I would like $uibModal to load it as brand new HTML instead.
How to remove angular $modal cache?
Can I make $uibModal reload the template as brand new HTML each time? More like $.load in jQuery?
All templates you load in the Angular app are stored in the $templateCache so they will not be downloaded the next time you are referring to them.
In your case, this is not the desired behavior as the HTML contents of the same URL may change over time.
Therefore, you have to remove the cached URL from the cache before opening the modal with
$templateCache.remove(scope.modalUrl);
Also, see How to remove angular $modal cache.
Another idea is to override the $templateCache's put method so it does not store some particular paths.
angular.module('yourApp').decorator('$templateCache', function($delegate) {
var originalPut = $delegate.put;
$delegate.put = function (templatePath, contents) {
// specifiy conditions which would tell what paths should not be cached
if (templatePath == '/this-should-not-be-cached.html' || templatePath.match(/some-regex/)) {
return;
}
else {
originalPut(templatePath, contents);
}
};
return $delegate;
});
You can't just disable $templateCache because many libraries use it to store the templates that are shipped with them (e.g. ui-bootstrap and similar).

Controller method not found when button inside template is pressed

I'm creating a project using NodeJS, Express and AngularJS that will have a search form (added via custom directive) and a search results that must be loaded only after the search button is pressed.
The problem is that the method I have created inside the controller can't be found from the search form.
Here is a sample of my code:
app.js
(function() {
var app = angular.module('app', ['app-directives']);
app.controller('AppController', function() {
this.buttonClick = function() {
alert('Test');
};
});
})();
directives.js
(function(){
var app = angular.module('app-directives', []);
app.directive('searchForm', function() {
return {
retrict: 'E',
templateUrl: '/partials/search-form.html'
};
});
app.directive('searchResults', function() {
return {
retrict: 'E',
templateUrl: '/partials/search-results.html'
};
});
})();
search-form.html
<input type="text" id="query" />
<button onclick="buttonClick">Search</button>
page-content.html
<section id="mainContent">
<search-form></search-form>
<search-results></search-results>
</section>
UPDATE
The second question will be posted in another thread.
About your first question:
You are using onclick attribute instead angular's 'ng-click' in the button search. This could be the problem. And do not forget to also add the 'ng-app' and 'ng-controller' tags. If not, your method will never be visible.
I also would recommend you to use $scope service instead of 'this' for attaching models and functions you later will use in your views.
Regards

reusable modal windows design patterns angularJS

I have been trying to create a modal windows that are re-usable with angularJS.
While I am googling I come to know that re-usable modals are created by using
custom directives.
services.
I'm in a confusion which method to follow.
What is the most customized method for creating modal windows in angularJS? and any resources on how to create re-usable modal windows (design patterns for modal windows) in angularJS
Note: Please suggest solutions without angular-bootstrap-ui or bootstrap.
Update:
I am trying to develop a similar kind of screen.
when the user clicks on "select Bus" link a modal window will be displayed.
Title, Content of the modal window is based on the corresponding hyper link.
I've already done this screen by using custom directives with the help of
How to Create a Simple Modal Dialog Directive in Angular.js
But what I am going to rewrite it as a reusable module or directive.
So suggest some design patterns to create re usable custom modal dialog windows using angularJS
Please check the following link for re-usable windows in angular.
That may resolve your issues.
http://www.dwmkerr.com/the-only-angularjs-modal-service-youll-ever-need/
A fairly simple one is ng-modal (https://github.com/adamalbrecht/ngModal), it is a directive, meaning it is highly re-usable. Services are do-able as well, but they are meant to get/set/process data rather than display HTML; hence directives are the way to go.
I've used ng-modal and adding just a little code to it went a long way to make it super-reusable. You can place it in it's own controller and have it always injected so that you can open the modal and show a message or some html.
HTML:
<div ng-controller="modalCtrl">
<modal-dialog show='dialogShown' dialog-title='titleToUse' height='400px' width='75%'>
<p ng-bind="messageToShow"> </p>
<div ng-bind-html="someHTML"></div>
</modal-dialog>
</div>
JS:
myApp.controller('modalCtrl', function($scope){
$scope.titleToUse = "Modal Title";
$scope.messageToShow = "Testing Message"; // default message
$scope.someHTML = "<div>Whoa! A Div!</div>";
$scope.$on('changeMessageEvent', function($event, message){ // listens for change message event and sets new message
$scope.messageToShow = message;
});
});
myApp.controller('someOtherController', function($scope, $rootScope){ // import rootScope
var messageToSendToModal = "New Message!";
$rootScope.$broadcast('changeMessageEvent', messageToSendToModal );
});
Update:
If you want dynamic template and controllers, that is easily to do with ng-modal, you just have to use ng-include:
<div ng-controller="modalCtrl">
<modal-dialog show='dialogShown' dialog-title='titleToUse' height='400px' width='75%'>
<p ng-bind="messageToShow"> </p>
<div ng-bind-html="someHTML"></div>
<!-- some dynamic template -->
<ng-include src="pathToTemplate"></ng-include>
</modal-dialog>
</div>
where in modalCtrl you have
$scope.pathToTemplate = "/path/to/template.html";
that template can contain a controller and can be switched out dynamically via variables.
If anyone is looking for another example I just had a crack at creating a custom modal service and directive myself, with them you can add modals to views like this:
<button ng-click="vm.openModal('custom-modal-1')">Open Modal 1</button>
<modal id="custom-modal-1">
<div class="modal">
<div class="modal-body">
<h1>A Custom Modal!</h1>
<p>
Home page text: <input type="text" ng-model="vm.bodyText" />
</p>
<button ng-click="vm.closeModal('custom-modal-1');">Close</button>
</div>
</div>
<div class="modal-background"></div>
</modal>
Here's the controller that opens and closes the modal:
(function () {
'use strict';
angular
.module('app')
.controller('Home.IndexController', Controller);
function Controller(ModalService) {
var vm = this;
vm.openModal = openModal;
vm.closeModal = closeModal;
initController();
function initController() {
vm.bodyText = 'This text can be updated in modal 1';
}
function openModal(id){
ModalService.Open(id);
}
function closeModal(id){
ModalService.Close(id);
}
}
})();
This is the custom modal service:
(function () {
'use strict';
angular
.module('app')
.factory('ModalService', Service);
function Service() {
var modals = []; // array of modals on the page
var service = {};
service.Add = Add;
service.Remove = Remove;
service.Open = Open;
service.Close = Close;
return service;
function Add(modal) {
// add modal to array of active modals
modals.push(modal);
}
function Remove(id) {
// remove modal from array of active modals
var modalToRemove = _.findWhere(modals, { id: id });
modals = _.without(modals, modalToRemove);
}
function Open(id) {
// open modal specified by id
var modal = _.findWhere(modals, { id: id });
modal.open();
}
function Close(id) {
// close modal specified by id
var modal = _.findWhere(modals, { id: id });
modal.close();
}
}
})();
And this is the custom modal directive:
(function () {
'use strict';
angular
.module('app')
.directive('modal', Directive);
function Directive(ModalService) {
return {
link: function (scope, element, attrs) {
// ensure id attribute exists
if (!attrs.id) {
console.error('modal must have an id');
return;
}
// move element to bottom of page (just before </body>) so it can be displayed above everything else
element.appendTo('body');
// close modal on background click
element.on('click', function (e) {
var target = $(e.target);
if (!target.closest('.modal-body').length) {
scope.$evalAsync(Close);
}
});
// add self (this modal instance) to the modal service so it's accessible from controllers
var modal = {
id: attrs.id,
open: Open,
close: Close
};
ModalService.Add(modal);
// remove self from modal service when directive is destroyed
scope.$on('$destroy', function() {
ModalService.Remove(attrs.id);
element.remove();
});
// open modal
function Open() {
element.show();
$('body').addClass('modal-open');
}
// close modal
function Close() {
element.hide();
$('body').removeClass('modal-open');
}
}
};
}
})();
For more info you can check out this blog post

Multiple file upload directives and one submit button

I have multiple categories of file upload and the HTML given to me has these different categories and each having a file upload control for multiple files. All these sections(and hence the file upload for each sections) are shown in a single HTML. I created a file upload directive and I am using it for each upload section. This works and can handle a button called "Upload" click event and this button is a part of directive.
Now, there is a single button called "Upload All" on click of which I have to update all the files belonging to different sections at one go. So I have to upload files from all the directives on click of this button. How can i have this functionality.
I'm not sure if there are better ways of doing this but you could try:
Passing a value from the controller to all directives and then on each directive attach a $watch on that value. Then clicking the Upload All button would change the value, triggering all the directives to run.
Controller:
app.controller = function('Ctrl', function($scope) {
$scope.uploadAllFlag = false;
$scope.uploadAll = function() {
$scope.uploadAllFlag = !$scope.uploadAllFlag;
}
});
Directive:
app.directive = function('directive', function() {
return {
scope: { flag: '=' }
link: function(scope) {
scope.$watch('flag', function(){
//do your upload stuff
}
}
});
Or alternativelly, inject the $rootScope on your controller and broadcast an event which you could catch on the directives:
app.controller = function('Ctrl', function($rootScope, $scope) {
$scope.uploadAll = function(){
$rootScope.$broadcast('uploadAll');
};
});
app.directive = function('directive', function(){
link: function(scope) {
scope.$on('uploadAll', function(){
//do something
}
}
});
I created a simple jsfiddle. The main idea is included there: http://jsfiddle.net/VpmV2/45/
[1]http://jsfiddle.net/VpmV2/45/

Resources