UI Bootstrap Datepicker Popup not working with Modal and ControllerAs - javascript

I've seen a similar question asked around here and the answer seems to be that the variable managing whether or not the datepicker is opened should be on the parent scope. I thought I had done that here, but it's still not working. The difference between my code and all the others I've seen is that I'm using controller as and everyone else is using $scope. How should this be working with controller as?
Full Plnkr Here
Here is the main page
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />'); </script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<link rel="stylesheet" href="style.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.min.js" data-semver="1.4.6"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.1/ui-bootstrap-tpls.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl as main">
<button class="btn btn-primary" ng-click="main.openModal()">Open Modal</button>
</body>
</html>
Here is the modal
<div class="modal-header">
{{modal.title}}
</div>
<div class="modal-body">
<p class="input-group">
<input type="date"
class="form-control"
ng-model="modal.dt"
is-open="main.opened"
close-text="Close" />
<span class="input-group-btn">
<button type="button" class="btn btn-default" ng-click="main.opened = true">
<i class="glyphicon glyphicon-calendar"></i>
</button>
</span>
</p>
</div>
Here are the controllers
var app = angular.module('plunker', ['ui.bootstrap']);
app.controller('MainCtrl', function($modal) {
var main = this;
main.openModal = function() {
var modalInstance = $modal.open({
templateUrl: 'modal.html',
controller: 'ModalInstanceCtrl as modal',
size: 'sm'
});
};
});
app.controller('ModalInstanceCtrl', function($modalInstance) {
var modal = this;
modal.title = 'Modal Title';
});

You've forgotten the datepicker-popup attribute on the input element:
<input type="date" datepicker-popup
class="form-control"
ng-model="main.dt"
is-open="main.opened"
close-text="Close" />
Also, you need to add the following code into your ng-click in order to stop the click event from propagating to the button's parent elements (clicking the parent div would immediately close the datepicker popup):
$event.preventDefault(); $event.stopPropagation();
e.g.
ng-click="$event.preventDefault(); $event.stopPropagation(); main.opened = true"
or put it into a method if you prefer.
Updated Plunker

Related

How can I create a modal list of values using just bootstrap and angular with springboot as a backend?

I am trying to make a generic "List of Values", a searchable modal with a natural identifier and a description. I have managed to create an angularjs app that does this in SpringBoot but it is not callable as a modal.
I want to use nothing but angularjs, bootstrap and springboot mvc, I don't want to get into node as the backend.
I attempted to follow the instructions here:
https://www.uibootstrap.net/angular-ui-bootstrap/angular-bootstrap-modal-example-demo/
But they are incomplete, code fragments. I have tried to put it all together and have the following three files:
At this point I am getting
Error: [$injector:modulerr] Failed to instantiate module TestApp due to:
[$injector:modulerr] Failed to instantiate module ui.bootstrap due to:
[$injector:nomod] Module 'ui.bootstrap' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
I don't even know where this would get ui.bootstrap and the installation instructions for it say to use npm, I want to know what files are being used and place them in my springboot project. Npm and node are not in the architectural plans.
index.html:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Model</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
<script src="./app.js"></script>
</head>
<body>
<div ng-app="TestApp">
<div class="well">
<button type="button" class="btn btn-primary" ng-click="openModal()">Click
to Open Modal Window!</button>
</div>
</div>
</body>
app.js:
var modalInstance = '';
var app = angular.module('TestApp', ['ui.bootstrap']);
app.controller('TestCtrl', function($scope, $http) {
function modalOpenCtrl($scope, payload){
console.log('fgfdfd');
$scope.datas = payload;
console.log($scope.datas);
$scope.closeModal = function(){
$scope.cancelModal();
}
}
$scope.openModal = function(task){
modalInstance = $uibModal.open({
animation: false,
templateUrl: './modal_window.html',
controller: 'modalOpenCtrl',
scope: $scope,
size: 'md',
backdrop: 'static',
resolve: {
payload: function () {
return {
msg_body : 'Hello! I am payload msg',
title : 'Hello! Title',
body_title : 'UiBootstrap.net'
};
}
}
});
}
function modalOpenCtrl($scope, payload){
console.log('fgfdfd');
$scope.datas = payload;
console.log($scope.datas);
$scope.closeModal = function(){
$scope.cancelModal();
}
}
})
modal_window.html:
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Model</title>
<link rel="stylesheet" type="text/css" href="css/bootstrap.css">
<script
src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
<script>
src="./app.js"
</script>
</head>
<body>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close" ng-click="closeModal()">
<span aria-hidden="true">×</span>
</button>
<div class="modal-title">
<h4>{{datas.title}}</h4>
</div>
</div>
<div class="modal-body log-view">
<div class="clearfix">
<h2>{{datas.body_title}}</h2>
<div>{{datas.msg_body}}</div>
</div>
</div>
<div class="modal-footer model-grey-color">
<div class="clearfix">
<div>
<button class="btn btn-success" ng-click="closeModal()">
<i class="ace-icon fa fa-ok"></i> Ok
</button>
<button class="btn btn-danger" ng-click="closeModal()">
<i class="fa fa-close"></i> Close
</button>
</div>
</div>
</div>
</body>
It seems you haven't connected linking between controller and view
The error Failed to instantiate module ui.bootstrap due to: you are getting due to it's not loaded and you are trying to use this module.
Please check below for how to show modal using ui.bootstrap
First you need to create proper directory structure in order to load files when application run in browser.
Directory structure example:
Now let's jump to index.html
index.html:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Model</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
</head>
<body>
<div ng-app="TestApp" ng-controller="TestCtrl">
<div class="well">
<button type="button" class="btn btn-primary" ng-click="openModal('abc')">Click
to Open Modal Window!</button>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-1.3.3.js"></script>
<script src="js/app.js"></script>
</body>
</html>
app.js
var modalInstance = '';
var app = angular.module('TestApp', ['ui.bootstrap']);
app.controller('TestCtrl', function($scope, $http,$uibModal) {
$scope.modalOpenCtrl = function($scope, payload){
console.log('fgfdfd');
$scope.datas = payload;
console.log($scope.datas);
$scope.closeModal = function(){
console.log("this is close modal")
$scope.cancelModal();
}
}
$scope.openModal = function(task){
modalInstance = $uibModal.open({
animation: false,
templateUrl: './main_window.html',
controller: 'modalOpenCtrl',
scope: $scope,
size: 'md',
backdrop: 'static',
resolve: {
payload: function () {
return {
msg_body : 'Hello! I am payload msg',
title : 'Hello! Title',
body_title : 'UiBootstrap.net'
};
}
}
});
}
$scope.cancelModal = function(){
console.log("this is final called");
modalInstance.close();
}
});
main_window.html
<div>
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close" ng-click="closeModal()">
<span aria-hidden="true">×</span>
</button>
<div class="modal-title">
<h4>{{datas.title}}</h4>
</div>
</div>
<div class="modal-body log-view">
<div class="clearfix">
<h2>{{datas.body_title}}</h2>
<div>{{datas.msg_body}}</div>
</div>
</div>
<div class="modal-footer model-grey-color">
<div class="clearfix">
<div>
<button class="btn btn-success" ng-click="closeModal()">
<i class="ace-icon fa fa-ok"></i> Ok
</button>
<button class="btn btn-danger" ng-click="closeModal()">
<i class="fa fa-close"></i> Close
</button>
</div>
</div>
</div>
</div>
That's it run this code and it will be open modal on button click
Note: This is just basic setup of angularjs. We can still improve this code if you have more features to built like routing, api calls, mvc pattern
Here is medium blog which explains some basics features of angularjs.
You need to add bootstrap script to your index.html file like <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>

AngularJS - show and hide arrow icon with glyphicon

I have a problem with the code, all I need is to hide the "NotesText" the arrow is pointing up, and after showing the "NotesText" arrow must be pointing down. I can not find the way to make this happen, please, I need help.
Basically, I need is to change the direction of the arrow agree if I need to show or hide
This is what I have .
This is HTML:
<div id="notes-controller" class="collapse in" ng-controller="NotesController">
<fieldset>
<legend class="translatable" data-i18n="Notes">Notes</legend>
<form novalidate class="simple-form">
<div class="container col-md-12" ng-show="$ctrl.param.note.visible">
<textarea class="col-md-12" ng-readonly="$ctrl.param.note.readonly" type="text" id="Notes" ng-model="$ctrl.notes.note" ng-model-options="{ getterSetter: true }" />
</div>
</form>
</fieldset>
</div>
<span type="button" class="glyphicon glyphicon-chevron-up" data-toggle="collapse" data-target="#notes-controller"></span>
This is Controller
angular.
module('notesText').
component('notesText', {
templateUrl: '/Scripts/test/notes-text/notes-text.template.html',
bindings: {
notes: '=',
param: '='
}
}).controller('NotesController', ['$scope', function ($scope) {
$scope.master = {};
$scope.update = function (user) {
$scope.master = angular.copy(user);
};
$scope.reset = function () {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}]);
This is how it looks:
enter image description here
A very Minimalistic Soln:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container" ng-app="">
<textarea id="myTextArea" ng-hide="isHidden">MY TEXT</textarea>
<br>
<span class="glyphicon" ng-class="isHidden ? 'glyphicon-chevron-down' : 'glyphicon-chevron-up'" ng-click="isHidden = !isHidden;">
</span>
</div>
A more verbose Soln:
Have a look at the working example below:
Simply using ng-class to attach glyphicon-chevron-up or glyphicon-chevron-down based on expression returned by a function that checks if the textarea is visible.
angular.module("myApp", [])
.controller("myCtrl", function($scope) {
$scope.isShown = function() {
return $('#myTextArea').is(':visible');
}
$scope.hideIt = function() {
$('#myTextArea').toggle();
}
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<div class="container" ng-app="myApp" ng-controller="myCtrl">
<textarea id="myTextArea">MY TEXT</textarea>
<br>
<span class="glyphicon"
ng-class="isShown() ? 'glyphicon-chevron-up' : 'glyphicon-chevron-down'"
ng-click="hideIt()">
</span>
</div>
Using the ng-show and ng-hide directive might be the best way to achieve this. That way you can have a scoped variable you can point to. You could also do an ng-class that if true, rotates the icon 180 degs. Either way it's up to you.
<span ng-show="$ctrl.IsToggled" type="button" class="glyphicon glyphicon-chevron-up" data-toggle="collapse" data-target="#notes-controller"></span>
<span ng-hide="$ctrl.IsToggled" type="button" class="glyphicon glyphicon-chevron-down" data-toggle="collapse" data-target="#notes-controller"></span>

Angularjs bootstrap popover blink after model change

I am using angularjs bootstrap popover inside a table.
The table is populated using ng-repeat and if the popover is open and i get new data to the table there is a flicker to the popover.
Here is a working example
Pknkr
Any thought on how can i prevent the flicker ?
<!doctype html>
<html ng-app="ui.bootstrap.demo">
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-2.0.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="PopoverDemoCtrl">
<br/>
<br/>
<table>
<tr ng-repeat="item in list">
<td>
<button uib-popover-template="dynamicPopover.templateUrl"
popover-is-open="aux.openPopOverId==item.id"
ng-click="aux.openPopOverId=item.id" popover-placement="right" type="button" class="btn btn-link">
Popover
</button>
</td>
</tr>
</table>
<script type="text/ng-template" id="myPopoverTemplate.html">
<div>{{dynamicPopover.content}}</div>
<div class="form-group">
<label>Popup Title:</label>
<input type="text" ng-model="dynamicPopover.title" class="form-control">
</div>
</script>
</div>
</body>
</html>
And the js
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('PopoverDemoCtrl', function ($scope,$interval, $sce) {
$scope.dynamicPopover = {
templateUrl: 'myPopoverTemplate.html',
title: 'Title'
};
$scope.list = [{'id':1},{'id':2},{'id':3}];
$scope.aux = {'openPopOverId':2};
$scope.updateList = function(){
$scope.list = [{'id':1},{'id':2},{'id':3}];
}
$interval($scope.updateList,500,0);
});
I thought this could be help you please read here in detail..

How to use ng-disabled to prevent user from resubmitting form

I'm trying to prevent user from resubmitting the login form with the code below
<button class="submit" ng-disabled="form_login.$submitted" type="submit"></button>
But this will disable the submit button as long as the button is clicked, even when user submit invalid data. What is the right way to stop submit button only after valid information submitted?
You can use ng-required attribute(directive) which will check the dirty state of the element.
Try this:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<form action="#" method="post" name="myForm">
Name::
<input type="text" ng-model="name" ng-required='true'>
<input type="submit" ng-disabled="myForm.$invalid" value="Submit">
</form>
</body>
</html>
Live example
Though your question is not clear, But you can try this ,
Here is HTML :
<form action="#" method="post">
Name::<input type="text" ng-model="name" ng-keyup="dirty()">
Address::<input type="text" ng-model="address" ng-keyup="dirty()">
<input type="submit" ng-disabled="error" value="Submit">
</form>
and here is JS :
angular.module('myApp', []).controller('ctrl', function($scope){
$scope.error = true; //Disables button initially
$scope.dirty = function(){
if($scope.name!='' && $scope.address!='')//Check conditions here
{
$scope.error = false; //Enables the button
}
}
});

angularjs view not getting updated

Here is a small self-contained html todo application using routes...
It has two views - list.html and add.html
list.html:
<div>
Add Task
<br />
<br />
<div class="container" id="tasks">
<ul>
<li ng-repeat="task in tasks">
<button ng-show="!task.done" ng-click="markTaskAsDone(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-ok-circle"></span></button>
<button ng-show="task.done" ng-click="markTaskAsNotDone(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-pushpin"></span></button>
<button ng-click="removeTask(task)" class="btn btn-default btn-xs"><span class="glyphicon glyphicon-remove-circle"></span></button>
<s ng-show="task.done">{{task.desc}}</s>
<span ng-show="!task.done">{{task.desc}}</span>
</li>
</ul>
<p ng-show="tasks.length == 0">Add few tasks</p>
</div>
</div>
add.html:
<div>
<span class="glyphicon glyphicon-arrow-left"></span> Back
<h2>Add a task</h2>
<div class="form-inline">
<input type="text" data-ng-model="newTask.desc" placeholder="Enter Task..." class="form-control" />
Add
</div>
</div>
I only have one controller.
controllers = {
ToDoController: function ($scope, $timeout, $location) {
//two items in by default...
$scope.tasks = [
{ desc: 'Buy milk', done: false },
{ desc: 'Collect newspaper', done: false }
];
$scope.newTask = { desc: '', done: false };
$scope.addNewTask = function () {
$location.path('/');
console.log('a');
$scope.tasks.push($scope.newTask);
}
$scope.markTaskAsDone = function (task) {
task.done = true;
console.log($scope.tasks);
}
$scope.markTaskAsNotDone = function (task) {
task.done = false;
};
$scope.removeTask = function (task) {
$scope.tasks.splice($scope.tasks.indexOf(task), 1);
};
//called to set newTask
$scope.setNewTask = function () {
$scope.newTask = { desc: '', done: false };
};
}
};
My shell page looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ToDo List</title>
<!-- Bootstrap -->
<link href="Content/bootstrap.min.css" rel="stylesheet">
<link href="Content/bootstrap-theme.min.css" rel="stylesheet">
<style>
#tasks ul {
margin: 0px;
padding: 0px;
list-style: none;
font-size: large;
}
</style>
</head>
<body>
<h1>TODO App</h1>
<div data-ng-app="todoApp">
<div data-ng-view=""></div>
</div>
<script src="Scripts/jquery-1.9.0.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-route.min.js"></script>
<script src="Scripts/todo.js"></script>
<script>
var app = angular.module('todoApp', ['ngRoute']);
app.controller(controllers);
app.config(function ($routeProvider) {
$routeProvider
.when('/list', {
controller: 'ToDoController',
templateUrl: 'partials/list.html'
})
.when('/add', {
controller: 'ToDoController',
templateUrl: 'partials/add.html'
})
.otherwise({ redirectTo: '/list' });
});
</script>
</body>
</html>
Issue:
When I load index.html its shows the list.html. The two default items I've put shows up. I click on Add and navigate to the second view (add.html), enter details and click on the Add button in that page...I navigate to the list.html view, but its still showing the old list...not the updated list...
Surely missing some api call to do the update to the view...else this page is coming from some cache. What is the correct way to do this?
ToDoController is instantiated twice and separately for your two views. To maintain 1 instance of the controller to control both views, don't declare it in your routing, but declare it on a parent tag of the views.
For instance, like this:
<div data-ng-app="todoApp" data-ng-controller="ToDoController">
<div data-ng-view></div>
</div>
Even better is to write separate controllers for each view to put the view-specific logic into, and have 1 parent controller to store values that both controllers should have access to.
Another way to share scope among isolated controllers is using $rootScope, but you should normally try to avoid using that (like you would try to avoid using global variables in any programming language).

Categories

Resources