AngularJS: External Modal Templates - angularjs

I read Agularjs - include external html file into modals, but it didn't include much code or explanation and just pointed to docs that I've read. So, I will go into more detail.
I have a main html file for a SPA (Single Page Application). I want to use modals for more detailed views.
<html>
<head>
<meta charset='utf-8'>
<script src="js/angular.js"></script>
<script src="js/angular-ui-bootstrap-modal.js"></script>
<script src="js/app.js"></script>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body ng-app="MyApp" ng-controller="MyCtrl">
<button class="btn" ng-click="open()">Open Modal</button>
<!-- want this to be in a separate html file -->
<div modal="showModal" close="cancel()">
<div class="modal-header">
<h4>Modal Dialog</h4>
</div>
<div class="modal-body">
<p>Example paragraph with some text.</p>
</div>
<div class="modal-footer">
<button class="btn btn-success" ng-click="ok()">Okay</button>
<button class="btn" ng-click="cancel()">Cancel</button>
</div>
</div>
<!-- -->
</body>
</html>
And my app.js file:
var app = angular.module("MyApp", ["ui.bootstrap.modal"]);
app.controller("MyCtrl", function($scope) {
$scope.open = function() {
$scope.showModal = true;
};
$scope.ok = function() {
$scope.showModal = false;
};
$scope.cancel = function() {
$scope.showModal = false;
};
});
What would I need to add to app.js in order for it to be able to display external html files as modals on my main html page?

I've done this plnkr so as to explain it better
To open the modal defined in a dedicated html template :
1. The following is declared in the controller responsible for the button opening the modal :
$modal.open({
templateUrl: 'myModalTemplate.html',
controller: 'MyModalController'
});
2. This is in the controller of the modal :
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
See also ui bootstrap doc

Please take look the documentation carefully here
You can do something like this with templateUrl
var modalInstance = $modal.open({
animation: $scope.animationsEnabled,
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
items: function () {
return $scope.items;
}
}
});

Related

angularjs $uimodal needs to be updated

i have a peculiar scenario, where my data gets updated even after a modal window is open. i am supposed to refresh the data on the modal pop-up by adding a new item on the modal popup.
Here is the plunker, i tried to pass $rootScope, but from documentation, realized that default scope passed is $rootScope.
My plunker link is
https://plnkr.co/edit/hnMGHfsxPfq8BRCtVxqJ
I'm using angular ui bootstrap and using $uibModal
Please suggest a solution i can try.
In my plunker code, even if the $item is updated, my modal isnt being refreshed.
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-animate.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular-sanitize.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.5.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="ModalDemoCtrl as $ctrl" class="modal-demo">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body" id="modal-body">
<ul>
<li ng-repeat="item in $ctrl.items">
{{ item }}
</li>
</ul>
Selected: <b>{{ $ctrl.selected.item }}</b>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="$ctrl.ok()">OK</button>
<button class="btn btn-warning" type="button" ng-click="$ctrl.cancel()">Cancel</button>
</div>
</script>
<script type="text/ng-template" id="stackedModal.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title-{{name}}">The {{name}} modal!</h3>
</div>
<div class="modal-body" id="modal-body-{{name}}">
Having multiple modals open at once is probably bad UX but it's technically possible.
</div>
</script>
<button type="button" class="btn btn-default" ng-click="$ctrl.open()">Open me!</button>
<button type="button" class="btn btn-default" ng-click="$ctrl.additems()">Add Item</button>
{{ $ctrl.items}}
<div class="modal-parent">
</div>
</div>
</body>
</html>
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($uibModal, $log, $document) {
var $ctrl = this;
$ctrl.items = ['item1', 'item2', 'item3'];
$ctrl.animationsEnabled = true;
$ctrl.additems = function (){
$ctrl.items.push("item"+($ctrl.items.length+1));
};
$ctrl.open = function (size, parentSelector) {
var parentElem = parentSelector ?
angular.element($document[0].querySelector('.modal-demo ' + parentSelector)) : undefined;
var modalInstance = $uibModal.open({
animation: $ctrl.animationsEnabled,
ariaLabelledBy: 'modal-title',
ariaDescribedBy: 'modal-body',
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
controllerAs: '$ctrl',
size: size,
appendTo: parentElem,
resolve: {
items: function () {
return $ctrl.items;
}
}
});
setTimeout(function () {
$ctrl.items.push("item"+($ctrl.items.length+1));
}, 1000);
modalInstance.result.then(function (selectedItem) {
$ctrl.selected = selectedItem;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
$ctrl.toggleAnimation = function () {
$ctrl.animationsEnabled = !$ctrl.animationsEnabled;
};
});
// Please note that $uibModalInstance represents a modal window (instance) dependency.
// It is not the same as the $uibModal service used above.
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($uibModalInstance, items) {
var $ctrl = this;
$ctrl.items = items;
$ctrl.selected = {
item: $ctrl.items[0]
};
$ctrl.ok = function () {
$uibModalInstance.close($ctrl.selected.item);
};
$ctrl.cancel = function () {
$uibModalInstance.dismiss('cancel');
};
});
My issue specifically is here, the Modal is rendered already with items passed.
ctrl.items is updated after 1 second, but the modal window where items is passed is not updated. Is there a way i can send an update of $ctrl.items to modal window
setTimeout(function () {
$ctrl.items.push("item"+($ctrl.items.length+1));
}, 1000);
Your question was not very clear. From your plunkr I see that the modal data gets updated when the original data is modified. So, assuming that's your problem: Javascripts objects are copied by reference. So to avoid that you need to create a new copy of the object. Like so:
items: function () {
return angular.copy($ctrl.items);
}
Updated plunkr: https://plnkr.co/edit/pHDr0B0jWRBGeNSPu0t7?p=preview

How do I display the inner html of directive inside a dialog?

What do I want to do?
I want to have a directive with some html inside. The directive renders a button and when the button is clicked I open a modal dialog. I want to display the html declared inside the directive in the dialog. Different spots where I use the directive might have different html messages in the modal dialog.
Here is the code that I've got.
app.js:
var app = angular.module('plunker', ['ngResource', 'ui.bootstrap', 'ui.bootstrap.modal']);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
})
.controller('dialogController', ['$scope', '$modalInstance', 'params', function ($scope, $modalInstance, params) {
$scope.info = params.info;
$scope.close = function () {
$modalInstance.dismiss('cancel');
};
}])
.directive('someDirective', ['$modal', '$timeout', function ($modal, $timeout) {
return {
scope: {
title: '#title'
},
restrict: 'AE',
replace: true,
templateUrl: 'someDirective.html',
transclude: true,
link: function ($scope, $element, attr, controller, transclude) {
//transclude(function(clone, scope) {
// debugger;
// });
$scope.info = "test"; // I would like to set this to the value within the inner html of the directive.
$scope.openDialog = function () {
var modalInstance = $modal.open({
templateUrl: 'dialog.html',
controller: 'dialogController',
backdrop: 'static',
windowClass: 'ie-app-modal-window-narrow',
resolve: {
params: function () {
return {
info: 'SomeHtml' //<-- here I want to it to the html from inside someDirective
};
}
}
});
modalInstance.result.then(function () {
},
function () { });
};
}
};
}])
;
dialog.html:
<!DOCTYPE html>
<html>
<head>
<title>Add attachment</title>
<meta charset="utf-8"/>
</head>
<body>
<div class="modal-header">
<button type="button" class="close"><span aria-hidden="true" ng-click="close()">×</span></button>
<strong>Add Attachment</strong>
</div>
<div class="modal-body">
<!-- Text input-->
<div class="alert alert-info" role="alert">
{{info}}
</div>
</div>
<div class="modal-footer">
<div class="form-group">
<div style="float: left">
<button class="btn btn-default" ng-click="close()" ng-disabled="isDisabled">Close</button>
</div>
</div>
</div>
</body>
</html>
index.html:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script data-require="jquery#2.2.4" data-semver="2.2.4" src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<link data-require="bootstrap#3.3.7" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<script data-require="bootstrap#3.3.7" data-semver="3.3.7" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.28/angular.js" data-semver="1.2.28"></script>
<script data-require="angular-ui#0.4.0" data-semver="0.4.0" src="http://rawgithub.com/angular-ui/angular-ui/master/build/angular-ui.js"></script>
<script data-require="angular-ui-bootstrap#1.3.3" data-semver="0.12.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.0.min.js"></script>
<script data-require="angular-resource#1.2.28" data-semver="1.2.28" src="https://code.angularjs.org/1.2.28/angular-resource.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<p>Hello {{name}}!</p>
<some-directive title="Hello">
<b>Testing</b>
</some-directive>
</body>
</html>
someDirective.html:
<div class="panel panel-default" >
<div class="panel-heading">
{{title}}
</div>
<div class="panel-body" ng-style="loadingStyle">
<button class="btn btn-sm btn-default" ng-click="openDialog();" type="button">Open</button>
</div>
</div>
I found this: How to get inner html of custom directive? but I don't know exactly how it would work in my case. I am not using the compile method.
Plnker
Thanks
To Pass value from someDirective to dialog.
First inject $rootScope into someDirective like so:
directive('someDirective', ['$modal', '$timeout', '$rootScope', function ($modal, $timeout, $rootScope) {
Now we create a new scope and add a value to it (in this case, $scope.info), and pass it into the modalScope. angular will then pass this along to the modal's controller as the $scope variable.
$scope.info = "test";
$scope.openDialog = function () {
var modalScope = $rootScope.$new();
modalScope.info = $scope.info;
var modalInstance = $modal.open({
scope: modalScope,
templateUrl: 'dialog.html',
controller: 'dialogController',
backdrop: 'static',
windowClass: 'ie-app-modal-window-narrow',
});
modalInstance.result.then(function () {
},
function (result) {
});
};
So inside the modal's controller we have access to variable we just passed in!
.controller('dialogController', ['$scope', '$modalInstance', function ($scope, $modalInstance) {
console.log($scope.info); //prints "test"
$scope.close = function () {
$modalInstance.dismiss('cancel');
};
}])
Now the opposite. To pass from modal back to someDirective:
There's several ways but in my opinion the best way is to use the promises. modalInstance.result returns a promise. This promise is resolved if the modal is closes and rejected if the modal is dismissed. Whether resolved or rejected, a value/object can be passed along as a parameter.
Example, opening the dialog as before:
$scope.info = "test";
$scope.openDialog = function () {
var modalScope = $rootScope.$new();
modalScope.info = $scope.info;
var modalInstance = $modal.open({
scope: modalScope,
templateUrl: 'dialog.html',
controller: 'dialogController',
backdrop: 'static',
windowClass: 'ie-app-modal-window-narrow',
});
modalInstance.result.then(function (returnStuff) {
//This is called when the modal is closed.
//returnStuff is whatever you want to return from the dialog when it's closed
},
function (returnStuff) {
//This is called when the modal is dismissed.
//returnStuff is whatever you want to return from the dialog when it's dismissed
});
};
And to actually close/cancel the dialog:(from inside the dialog)
//pass any value you want back
$modalInstance.close({foo:"Ayyylmao", bar:42});
$modalInstance.dismiss('dismissed');
If I understood it correctly, this is what you want, http://plnkr.co/edit/tOe8tZ5VWfOCkocQaEKo?p=preview
$scope.info = $element.get(0).innerHTML.trim();
Based on this posting, I managed to find something that works for the specific angularjs versions that I am using. I made another plnkr.
The relevant changes are:
dialog.html: I used <div ng-bind-html="info"></div>
<!DOCTYPE html>
<html>
<head>
<title>Add attachment</title>
<meta charset="utf-8"/>
</head>
<body>
<div class="modal-header">
<button type="button" class="close"><span aria-hidden="true" ng-click="close()">×</span></button>
<strong>Add Attachment</strong>
</div>
<div class="modal-body">
<!-- Text input-->
<div class="alert alert-info" role="alert">
<div ng-bind-html="info"></div>
</div>
</div>
<div class="modal-footer">
<div class="form-group">
<div style="float: left">
<button class="btn btn-default" ng-click="close()" ng-disabled="isDisabled">Close</button>
</div>
</div>
</div>
</body>
</html>
app.js - I added the controller property in the someDirective directive and the code grabs the html and sets the info property.
var app = angular.module('plunker', ['ngResource', 'ui.bootstrap', 'ui.bootstrap.modal']);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
})
.controller('dialogController', ['$scope', '$modalInstance', 'params', function($scope, $modalInstance, params) {
$scope.info = params.info;
$scope.close = function() {
$modalInstance.dismiss('cancel');
};
}])
.directive('someDirective', ['$modal', '$timeout', '$sce', function($modal, $timeout, $sce) {
return {
scope: {
title: '#title',
html: '#'
},
restrict: 'AE',
replace: true,
templateUrl: 'someDirective.html',
transclude: true,
controller: function($scope, $element, $attrs, $transclude) {
$transclude(function(clone,scope){
$scope.info = angular.element('<div>').append(clone).html().trim();
});
},
link: {
pre: function (scope, iElement, iAttrs, controller) {
//debugger;
},
post: function($scope, $element, attr, controller) {
//transclude(function(clone, scope) {
// debugger;
// });
//debugger;
//$scope.info = "test"; // I would like to set this to the value within the inner html of the directive.
//debugger;
$scope.openDialog = function() {
var modalInstance = $modal.open({
templateUrl: 'dialog.html',
controller: 'dialogController',
backdrop: 'static',
windowClass: 'ie-app-modal-window-narrow',
resolve: {
params: function() {
return {
info: $sce.trustAsHtml($scope.info) //<-- here I want to set it to the html from inside someDirective
};
}
}
});
modalInstance.result.then(function() {},
function() {});
};
}
}
};
}])
;

Angular UI bootstrap modal is not working

I am new to angular and bootstrap. This is my Plunk.
This is my code of DemoController:
angular.module('app', ['ui.bootstrap'])
.controller('demoController', function($modal) {
this.message = 'It works!';
key = 1000;
this.modalInstance = this.modal = function(){
$modal.open({
controllerAs: 'modalController as modal',
templateUrl: 'modal.html',
resolve: {
key: function() {
return key;
}
}
});
};
this.modalInstance.result.then(function (optionSelected){
if(optionSelected == 'yes')
{
}
});
});
ModalController:
angular.module('app')
.controller('modalController', function($scope, $modalInstance, key) {
$scope.featureName = key;
$scope.yes = function () {
$modalInstance.close('yes');
};
$scope.discard = function () {
$modalInstance.close('discard');
};
$scope.goback = function () {
$modalInstance.close('goback');
};
});
Modal.html:
<script type="text/ng-template" id="modal.html">
<div class="modal-content">
<div class="modal-body">
<p>Do you want to save the changes to {{featureName}} </p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" ng-click="yes()">Yes</button>
<button type="button" class="btn btn-default" ng-click="discard()">Discrad</button>
<button type="button" class="btn btn-default" ng-click="goback()">Go Back</button>
</div>
</div>
</script>
Index.html:
<!DOCTYPE html>
<html>
<head>
<link data-require="bootstrap-css#3.1.1" data-semver="3.1.1" rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script data-require="angular.js#1.2.16" data-semver="1.2.16" src="https://code.angularjs.org/1.2.16/angular.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.11.0/ui-bootstrap-tpls.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="demoController as demo">
<h1>{{ demo.message }}</h1>
<button class="btn btn-primary" ng-click="demo.modal()">Open modal</button>
</body>
</html>
I want to pass data from demo controller to modal controller. I want to have separate html and controller for the modal dialog. Somehow this is not working.
Here's a working plunker based on your own plunk: http://plnkr.co/edit/VDDyDuBoZ30tAk2kQKoc?p=preview
List of changed things:
In index.html, I added Ctrl.js to the list of loaded scripts.
In modal.html, removed the script tags surrounding the html. When loading the modal html from an external file, the script tags aren't necessary.
Finally in script.js made a few changes, ending up with the following:
angular.module('app', ['ui.bootstrap'])
.controller('demoController', function($modal) {
this.message = 'It works!';
var key = 1000;
this.modal = function() {
var modalInstance = $modal.open({
controller: 'modalController',
templateUrl: 'modal.html',
resolve: {
key: function() {
return key;
}
}
});
modalInstance.result.then(function(optionSelected) {
if (optionSelected === 'yes') {
console.log("Yes selected!")
}
})
}
});
Basically, this.modal is the function that's executed when clicking on the Open modal button. In the function, we initialize a variable modalInstance, which is the $modal.open function call. We also handle the modal result inside the this.modal function, not outside of it.
You have a lot of mistakes there. Here is your example:
plnkr.co/edit/47WJrWHW7ueYXBpiYJbA?p=preview

Issue with binding data from Modal Dialog to another area of web app

I've been searching around for a solution to a problem, which I believe should be relatively easy to solve - that being the use of Angular.js's two-way databinding
I have a modal dialog (using the Angular ui-bootstrap code for modal dialog) from which I want to take inputted text and output to the main application page, I've got a working Plunker (it works with data-binding as I can see the input value in the modal dialog), however i'm wanting to take that value and bind it to the section under Projects
my html
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.3.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="ModalDemoCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">Add Project</h3>
</div>
<div class="modal-body">
Project Name: <input type="text" ng-model="name"></input>
{{name}}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
In Modal: {{ name }}
</script>
<button class="btn btn-default" ng-click="open()">Add Project</button>
</div>
<div class="col-lg-6">
<div class="table-responsive" ng-model="name">
<table class="table">
<thead>
<tr>
<th>Project</th>
<th>Badges</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{$scope.name}}</td>
</tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
my javascript
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('ModalDemoCtrl', function ($scope, $modal, $log) {
$scope.name = "";
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'myModalContent.html',
controller: 'ModalInstanceCtrl',
size: size,
resolve: {
projName: function () {
return $scope.name;
}
}
});
modalInstance.result.then(function (pName) {
$scope.name = pName;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});
};
});
// Please note that $modalInstance represents a modal window (instance) dependency.
// It is not the same as the $modal service used above.
angular.module('ui.bootstrap.demo').controller('ModalInstanceCtrl', function ($scope, $modalInstance, projName) {
$scope.name = projName;
$scope.ok = function () {
$modalInstance.close($scope.name);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
});
Many Thanks in advance
As the main application page is operated by ModalDemoCtrl controller and model is operated by ModalInstanceCtrl controller, so they can't use the scope variable of each other, these controllers have no relationship.
There is the only way to pass ModalDemoCtrl scope variable data to ModalInstanceCtrl, using resolve method of $model service, as you did.
resolve:{items: function () {return $scope.items;}
and ModalInstanceCtrl scope data to ModalDemoCtrl using $modalInstance.close(modeldata), which you did.
so if you want to pass the modal input to main application. use it as below ...
In ModalInstanceCtrl
$scope.ok = function () {
$modalInstance.close($scope.name);
};
In ModalDemoCtrl
modalInstance.result.then(function (nameFromModal) {
$scope.name = nameFromModal;
}, function () {
$log.info('Modal dismissed at: ' + new Date());
});

Angularjs modal window with routeProvider

I'm having trouble using routeProvider to display a modal window. I am displaying a table list of ingredients and hoping that by clicking on an ingredient, I can display an "update" modal. The table displays properly and I can even view a single ingredient outside of a modal context but as soon as I try and get the modal working everything falls apart - in fact, the modal doesn't even properly receive its "ingredient" variable. When clicking on a table row the HTML for the modal is displayed like it's a separate page.
app.js:
angular.module('IngredientsApp', [
'IngredientsApp.controllers',
'IngredientsApp.services',
'ngRoute',
'ui.bootstrap'
]).config(['$routeProvider', function($routeProvider) {
$routeProvider.
when("/ingredients", {templateUrl: "partials/ingredients.html", controller: "ingredientsController"}).
when("/ingredient/:id", {templateUrl: "partials/ingredient.html", controller: "ingredientController"}).
otherwise({redirectTo: '/ingredients'});
}]);
services.js:
angular.module('IngredientsApp.services', []).factory('ingredientAPIservice', function($http) {
var ingredientAPI = {};
ingredientAPI.getIngredients = function() {
return $http.get('/ingredient');
}
ingredientAPI.getIngredient = function(id) {
return $http.get('/ingredient/'+id+'/edit');
}
return ingredientAPI;
});
index.html
<!doctype html>
<html lang="en">
<head>
<title>Our Recipes</title>
<script type="text/javascript" src="/js/angular.min.js"></script>
<script type="text/javascript" src="/js/angular-route.min.js"></script>
<script type="text/javascript" src="/js/angular-bootstrap.min.js"></script>
<script type="text/javascript" src="/js/app.js"></script>
<script type="text/javascript" src="/js/services.js"></script>
<script type="text/javascript" src="/js/controllers.js"></script>
<link rel="stylesheet" type="text/css" href="/css/styles.css" />
</head>
<body ng-app="IngredientsApp">
<ng-view></ng-view>
</body>
</html>
ingredients.html
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Existing Ingredients</th>
<th><input type="text" ng-model="descriptionFilter" placeholder="Search..."/></th>
</tr>
</thead>
<tbody>
<tr ng-repeat="i in ingredientsList | filter: searchFilter">
<td>
<a href="/#/ingredient/{{i.Id}}">
{{i.Description}}
</a>
</td>
<td>Created at {{i.CreatedAt}}</td>
</tr>
</tbody>
</table>
ingredient.html
<script type="text/ng-template">
<div class="modal-header">
<h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
{{ingredient.Description}}
</div>
<div class="modal-footer">
<button class="btn btn-primary" ng-click="ok()">OK</button>
<button class="btn btn-warning" ng-click="cancel()">Dismiss</button>
</div>
</script>
controllers.js:
angular.module('IngredientsApp.controllers', []).controller('ingredientsController', function($scope, ingredientAPIservice) {
$scope.descriptionFilter = null;
$scope.ingredientsList = [];
$scope.searchFilter = function (ingredient) {
var keyword = new RegExp($scope.descriptionFilter, 'i');
return !$scope.descriptionFilter || keyword.test(ingredient.Description);
};
ingredientAPIservice.getIngredients().success(function (response) {
//Dig into the responde to get the relevant data
$scope.ingredientsList = response;
});
})
var ingredientController = function($scope, $routeParams, $modal, ingredientAPIservice) {
$scope.id = $routeParams.id;
$scope.ingredient = null;
ingredientAPIservice.getIngredient($scope.id).success(function (response) {
$scope.ingredient = response;
$scope.open = function (size) {
var modalInstance = $modal.open({
templateUrl: 'partials/ingredient.html',
controller: 'ingredientModalController',
size: size,
resolve: {
ingredient: function () {
console.log($scope.ingredient);
return $scope.ingredient;
}
}
});
}
});
}
var ingredientModalController = function($scope, $modalInstance, ingredient) {
$scope.ingredient = ingredient;
$scope.ok = function () {
$modalInstance.close($scope.ingredient);
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
}
I believe your issue is in app.js. Your route change causes the modal template (partials/ingredients.html) to be the only template displayed in ui-view. For the modal to work, you need to have the ingredients template nested within the ingredient template so both templates can be displayed at the same time. There are multiple ways to accomplish this.
If you are willing to give up the route change, just remove
when("/ingredient/:id", {templateUrl: "partials/ingredient.html", controller: "ingredientController"})
If you need the url to change, then I would look at doing it manually through the build in location service. https://docs.angularjs.org/guide/$location
You could just call a function that changes the url on click of an ingredient.

Resources