Displaying Error Message in Bootstrap Modal in Spring MVC Project - spring-mvc

Is it possible to display "User with this username does not exist" Error Message in Bootstrap Modal in Spring MVC Project through the controller?
login.jsp
<div class="modal-body">
<form id="register-form" role="form" autocomplete="off" class="form"
method="POST"
action="${pageContext.request.contextPath }/recoverPassword">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i
class="glyphicon glyphicon-envelope color-blue"></i></span> <input
id="email" name="username" placeholder="your username"
class="form-control" type="text"> ${error}
</div>
</div>
<input type="hidden" name="${_csrf.parameterName}"
value="${_csrf.token}" />
<button class="btn btn-lg btn-primary btn-block" type="submit">
Send email link</button>
</form>
controller
#RequestMapping(value = "/recoverPassword", method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.NO_CONTENT)
public void sendingEmailForForgot(#RequestParam("username") String username) {
// Check whether email exists in DB
System.out.println(userDAO.getUserByName(username));
System.out.println(username);
if (userDAO.getUserByName(username) == null) {
System.out.println("This ID does not exists");
redirectAttributes.addAttribute("error", "wrong");
} else {
System.out.println("mail sent to your id");
}
// If exists then hash and send url link
// else error
}
I have validated username whether if exists, but how to display that error on same currently opened modal?
If not possible through controller please share any other way to do so.

Finally solved it through AJAX, still don't know if possible through the controller. Works fine for me, I have used this:
function doAjaxPost() {
// get the form values
var name = $('#name').val();
var education = $('#education').val();
$.ajax({
type: "POST",
url: contexPath + "/AddUser.htm",
data: "name=" + name + "&education=" + education,
success: function(response){
// we have the response
if(response.status == "SUCCESS"){
userInfo = "<ol>";
for(i =0 ; i < response.result.length ; i++){
userInfo += "<br><li><b>Name</b> : " + response.result[i].name +
";<b> Education</b> : " + response.result[i].education;
}
userInfo += "</ol>";
$('#info').html("User has been added to the list successfully. " + userInfo);
$('#name').val('');
$('#education').val('');
$('#error').hide('slow');
$('#info').show('slow');
}else{
errorInfo = "";
for(i =0 ; i < response.result.length ; i++){
errorInfo += "<br>" + (i + 1) +". " + response.result[i].code;
}
$('#error').html("Please correct following errors: " + errorInfo);
$('#info').hide('slow');
$('#error').show('slow');
}
},
error: function(e){
alert('Error: ' + e);
}
});
}

Following trick worked for me
1. put ${error} in p tag with unique id
2. On login.jsp page load,check if innerHtml of p tag is empty.
3 If it is not empty open the login modal.
function modelopen(){
var temp = document.getElementById("errormsg").innerHTML;
if(temp!==""){
$('#modallogin').modal('show');
}

You can try:
1) RestController instead of Controller (I think that this is way you solved this)
2) You can use validations and return your error as part of BindingResult https://docs.spring.io/spring/docs/4.1.x/spring-framework-reference/html/validation.html
3) Use exceptionHandler

function errorshow() {
const input1 = document.getElementById('input1').value;
const input2 = document.getElementById('input2').value;
const div = document.getElementById("erroM");
if (input1 == '' && input2 == '') {
div.innerHTML = "hey";
setTimeout(() => {
div.remove()}, 2000);
}}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<title>Erorr Show in Modal</title>
</head>
<body>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form>
<div class="modal-body">
<div id="erroM"></div>
<div>
<input id="input1" type="text">
<input id="input2" type="text">
<input id="input3" type="text">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="errorshow()">save</button>
</div>
</form>
</div>
</div>
</div>
<!-- Button trigger modal -->
<button id="button" type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">Click</button>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
<script src="main.js"></script>
</body>
</html>

Related

What should I install to make my Firebase system recognize class="btn btn-action hide" ? (I assume it's a custom built CSS class?)

So the code below didn't work because the class="btn btn-action hide" is not recognized by the system because it is a custom built class by Firestore rather than a default built-in class in CSS. If that is the case, what should I install to make it work because I've already tried installing everything from Firebase and it still does not work?
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Firebase Web Quickstart</title>
<script
src="https://www.gstatic.com/firebasejs/live/3.1/firebase.js">
</script>
</head>
<body>
<div class="container">
<input id="txtEmail" type="email" placeholder="Email">
<input id="txtPassword" type="password" placeholder="Password">
<button id="btnLogin" class="btn btn-action">
Log in
</button>
<button id="btnSignUp" class="btn btn-secondary">
Sign Up
</button>
<button id="btnLogout" class="btn btn-action hide">
Log out
</button>
</div>
<script src="app.js"></script>
</body>
</html>
In the youtube example you've shown, it does not show you the css file. But I think it's using bootstrap from identifying the class name, here is what you can try:
Copy-paste the stylesheet link into your head before all other stylesheets to load our CSS.
<head>
<meta charset="utf-8">
<title>Firebase Web Quickstart</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">
<script src="https://www.gstatic.com/firebasejs/live/3.1/firebase.js"></script>
</head>
Please do note this is CDN, you can also download bootstrap yourself and add the file from your local path.
Update, the youtube video is using custom css that looks like bootstrap but it's not...to use bootstrap classes for button, see below:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Firebase Web Quickstart</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">
<script
src="https://www.gstatic.com/firebasejs/live/3.1/firebase.js">
</script>
</head>
<body>
<div class="container">
<input id="txtEmail" type="email" placeholder="Email">
<input id="txtPassword" type="password" placeholder="Password">
<button id="btnLogin" class="btn btn-primary">
Log in
</button>
<button id="btnSignUp" class="btn btn-secondary">
Sign Up
</button>
<button id="btnLogout" class="btn btn-danger" hidden>
Log out
</button>
</div>
<script src="app.js"></script>
</body>
</html>
These are the classes you can use:
https://getbootstrap.com/docs/4.0/components/buttons/
just use the firebase.auth().onAuthStateChanged will get similar purpose with out using bootstrapcdn but at first have to get document element id like below:
const txtEmail = document.getElementById('txtEmail');
const txtPassword = document.getElementById('txtPassword');
const btnLogin = document.getElementById('btnLogin');
const btnSignUp = document.getElementById('btnSignUp');
const btnLogout = document.getElementById('btnLogout');
firebase.auth().onAuthStateChanged(firebaseUser => {
if (firebaseUser) {
console.log(firebaseUser);
btnSignUp.style.display = "none";
} else {
console.log('not logged in');
btnLogout.style.display = "none";
}
})

Download text file via ASP.NET MVC dynamically changed

I have to generate file depending on input (checkboxes) and download it:
[HttpGet]
public FileResult GenerateFormatSettingsFile(IEnumerable<string> values)
{
var content = FileSettingsGenerator.Generate(values);
MemoryStream memoryStream = new MemoryStream();
TextWriter tw = new StreamWriter(memoryStream);
tw.WriteLine(content);
tw.Flush();
tw.Close();
return File(memoryStream.GetBuffer(), "text/plain", "file.txt");
}
And on my view this:
<button id="GenetateFormatSettingsFile" class="btn btn-primary" data-dismiss="modal" style="margin-right: 1500px">Generate</button>
$(document).ready(function() {
$("#GenetateFormatSettingsFile").click(function() {
var f = {};
var checkboxes = [];
$('input:checked').each(function() {
checkboxes.push($(this).attr("value"));
});
f.url = '#Url.Action("GenerateFormatSettingsFile", "Home")';
f.type = "GET";
f.dataType = "text";
f.data = { values: checkboxes},
f.traditional = true;
f.success = function(response) {
};
f.error = function(jqxhr, status, exception) {
alert(exception);
};
$.ajax(f);
});
});
</script>
The problem is the download doesn't start. How could I fix it?
If I do it with Html.ActionLink, the download starts, but I can't pass the values of checkboxes which is done by my ajax function above
Thanks!
Edit - that's how my check-boxes looks like:
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="modal" id="formatterSettings" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Settings</h4>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="defaultG">To default view</label>
<input class="form-control" type="checkbox" value="Default" id="defaultG">
</div>
<div class="form-group">
<label for="extendedG">To extended view</label>
<input class="form-control" type="checkbox" value="Extended" id="extendedG">
</div>
/div>
</form>
</div>
<div class="modal-footer">
<div class="col-md-6">
<button id="GenetateFormatSettingsFile" class="btn btn-primary" data-dismiss="modal" style="margin-right: 1500px">Generate</button>
#Html.ActionLink("Generate!", "GenerateFormatSettingsFile")
</div>
<div class="col-md-6">
<a class="btn btn-primary" data-dismiss="modal" >Generate From Code</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
Put a submit button in your form and POST your form synchronously (without ajax).
when a form is posted, values of all input elements (TextBoxes, CheckBoxes, ...) are sent to the server (with the request) and you don't need to do anything.

Google INVISIBLE reCaptcha + Bootstrap validator

I have a registration form with Bootstrap validator. I want to validate the google INVISIBLE reCaptcha (client-side) before submitting the form.
There is some exapmle (Invoking the invisible reCAPTCHA challenge after client side validation).
I tried to change this part:
function validate(event) {
event.preventDefault();
$('#form-reg').validator('validate').on('submit', function (e) {
if (e.isDefaultPrevented()) {
//...
} else {
grecaptcha.execute();
};
});
};
This does not work and I dont know if it's the right way.
Please advice how to join invisible reCaptcha and Bootstrap validator.
Thank you for your help.
The below code work for me
<?php
$config = require('config.php');
?>
<html>
<head>
<title>reCAPTCHA demo</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Boostrap Validator -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/1000hz-bootstrap-validator/0.11.9/validator.min.js" ></script>
<script type="text/javascript">
$(document).ready(function(){
$('#demo-form').validator().on('submit', function (e) {
if (e.isDefaultPrevented()) {
// handle the invalid form...
console.log("validation failed");
} else {
// everything looks good!
e.preventDefault();
console.log("validation success");
grecaptcha.execute();
}
});
});
function onSubmit(token){
document.getElementById("demo-form").submit();
};
</script>
</head>
<body>
<div class="container">
<br>
<div class="row">
<div class="col-md-5 col-md-offset-3">
<form id="demo-form" data-toggle="validator" role="form" action="admin.php" method="POST" >
<div class="form-group">
<label for="inputName" class="control-label">Name</label>
<input type="text" class="form-control" id="inputName" placeholder="Geordy James" required/>
</div>
<div id='recaptcha' class="g-recaptcha"
data-sitekey="<?php echo $config['client-key']; ?>"
data-callback="onSubmit"
data-size="invisible"></div>
<button class="btn btn-block btn-primary" type="submit">Submit</button>
</form>
</div>
</div>
</div>
<script src="https://www.google.com/recaptcha/api.js" async defer ></script>
</body>
</html>
I used Unofficial Google Invisible reCAPTCHA PHP library in this program and you can download it from https://github.com/geordyjames/google-Invisible-reCAPTCHA .
If this method doesn't work for you please comment below.

How to position ngshow messages in angular js

How to have ng-show messages beside the text box rather than underneath it. Right now it is displaying all the validation messages underneath the input box.
<!DOCTYPE html>
<html ng-app="myApp" >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script>
"use strict";
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.cityArray = ["hyderabad", "secunderabad", "delhi", "mumbai"];
$scope.submit = function ($event) {
if ($scope.myForm.$invalid) {
// Or some other update
$scope.myForm.$submitted = true;
$event.preventDefault();
}
};
});
app.directive('uniqueUsername', function ($http) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
element.bind('blur', function (e) {
ngModel.$setValidity('unique', true);
$http.post('CheckUserName2.do').success(function (data) {
if (data) {
ngModel.$setValidity('unique', false);
}
});
});
}
};
});
</script>
</head>
<body ng-controller="MainCtrl">
<div class="container">
<div class="col-md-6 col-md-offset-0">
<div class="panel panel-login">
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<h2 class="text-muted">Registration form</h2>
<div>
<form name="myForm" action="RegistrationServlet.do" method="POST" >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" unique-username="" placeholder="First Name" required/>
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span>
<span style="color:red" class="error" ng-if="myForm.$submitted && myForm.uname.$error.required">Please fill field above<br></span><br/>
<span style="color:red" class="hide-while-in-focus" ng-show="myForm.uname.$error.unique">Username already exist<br/></span>
<button class="form-control btn btn-success" type="submit" ng-click="submit($event)">Submit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Here's the plunker
You don't have space to the right to display error messages beside the input box. Putting error messages just above the submit button will cause a minor UI issue: with each error, your form submit-button will flicker vertically.
Viz.
- Submit your form without entering any input to get the error message.
- type/erase any character in the input box to see the flickering
Workaround:
Either keep the error messages below submit button or provide dedicated height to error messages to avoid undesirable effects or both
<form name="myForm" action="RegistrationServlet.do" method="POST" >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" unique-username="" placeholder="First Name" required/><br><br>
<button class="form-control btn btn-success" type="submit" ng-click="submit($event)">Submit</button>
<div style="height=100px">
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span>
<span style="color:red" class="error" ng-if="myForm.$submitted && myForm.uname.$error.required">Please fill field above<br></span><br/>
<span style="color:red" class="hide-while-in-focus" ng-show="myForm.uname.$error.unique">Username already exist<br/></span>
</div>
</form>
Demo

Retrieve an element by XPath/CSS from HTML

I am trying retrieve an element "Nature News Standard Article in Nature News & Comment" which is part of below HMTL code.
I have following WebDriver code in selenium:
if ("Polopoly CM".equals(driver.getTitle())) {
System.out.println("----> Title of page <----");
driver.findElement(By.xpath("//*[starts-with(#id,'nav_') and #class='p_textOutput']"));
System.out.println("----> Xpath Selected <----");
driver.findElement(By.xpath("//*[starts-with(#id,'nav_') and #class='p_textOutput']")).click();
System.out.println("----> Xpath Clicked <----");
}
Problem is: i am unable to retrive the required element through Xpath/CSS from HTML
HTML:
<document>
<html xmlns:polopoly="http://www.polopoly.com/polopoly/cm/app/gui" xmlns="http://www.w3.org/1999/xhtml" style="cursor: default;">
<head>
<body id="nav_3" class="navFrameBody" onbeforeunload="busyCursor();" onload="onLoad(); idleCursor();">
<script type="text/javascript"> <!-- Jasmine.createFrame('nav'); //--> </script>
<form id="mainform" name="mainform" method="post" action="CM">
<input type="hidden" value="2852906396" name="owid"/>**
<input type="hidden" value="1332852912984" name="ofid"/>
<input type="hidden" value="nav" name="ofn"/>
<input type="hidden" value="true" name="ofs"/>
<input id="nav_1" type="hidden" value="0" name="nav_1"/>
<input id="nav_2" type="hidden" value="0" name="nav_2"/>
<div id="nav_13_placeHolder" class="ajax_placeHolder">
<fieldset id="nav_14" class="field"/>
<div id="nav_4" class="p-group quickCreator expanded">
<div id="nav_4_state">
<input id="nav_15" type="hidden" value="expanded" name="nav_15"/>
</div>
<div class="toggleIcon clearfix"/>
<script lang="javascript">$(document).ready(function() {p_makeExpandable('nav_4', 'nav_15')});</script>
<fieldset id="nav_16" class="contentCreator field topContentCreator">
<div class="quickCreator contentCreator container">
<div class="quickCreator header clearfix">
<h2> Create New </h2>
<a id="nav_17" class="customize" href="javascript:actionEventData({$contentId:"18.232.1319560059", $action:"edit", $target:"work", $opentab:"menu/quickCreatorLayout"})">Customize</a>
</div>
<div class="list">
<div class="quickCreator link">
<input type="hidden" value="" name="nav_18"/>
<a id="nav_18" href="javascript:submitForm(document.mainform, document.mainform.nav_18, "x")">
<img id="nav_19" class="centered" alt="" src="images/icons/transparentIcon.png"/>
<span id="nav_20" class="p_textOutput">Nature News Standard Article in Nature News & Comment</span>
</a>
</div>
</div>
</div>
</fieldset>
</div>
<div id="nav_5" class="p-group contentTree expanded">
<div id="nav_5_state">
<input id="nav_21" type="hidden" value="expanded" name="nav_21"/>
</div>
<div class="toggleIcon clearfix"/>
<script lang="javascript">$(document).ready(function() {p_makeExpandable('nav_5', 'nav_21')});</script>
<div class="field contentTree">
<div id="nav_6_placeHolder" class="ajax_placeHolder">
<div class="header">
<span class="label">Content Tree</span>
<button id="nav_9" type="button" value="Refresh tree" name="nav_9">
<img id="nav_22" class="centered" alt="" src="images/icons/refresh.png"/>
<span id="nav_23" class="p_textOutput"> Refresh tree</span>
<script type="text/javascript"> <!-- jQuery(document).ready(function() { addOnClickEvent("nav_9",null, "nav_9_placeHolder", null, new IndicatorLifecycleHook('p.std_ajaxIndicator', true, 0.8, "createImageTop('images/ajax/busy_indicator_big_green.gif')")); }); //--> </script>
</button>
</div>
<div class="tree">
<div id="nav_8_placeHolder" class="ajax_placeHolder">
<script type="text/javascript"> jQuery.require(["script/polopoly-ui.js"]); </script>
<input id="nav_8" type="hidden" value="" name="nav_8"/>
<script type="text/javascript"> jQuery.require(["script/polopoly-ui.js"]); </script>
<ul id="nav_8_tree" class="tree">
</div>
</div>
</div>
</div>
</div>
<fieldset id="nav_24" class="field clipboard">
<input id="nav_25" type="hidden" value="" name="nav_25"/>
</fieldset>
</form>
<script type="text/javascript"> <!-- jQuery(document).ready(function() { if(window.parent.SeleniumPageLoadCountnav==null) { window.parent.SeleniumPageLoadCountnav=1; window.parent.SeleniumPageLoadCountnavOld=0; } else { window.parent.SeleniumPageLoadCountnav+=1; } }); //--> </script>
</body>
</html>
</document>
I see two elements which can be selected by your xpath locator. Try to find both of them.
List<WebElement> elements = webDriver.findElements(By.xpath("your_xpath"));
for (Element element : elements) {
element.click();
}
Your HTML code is:
Nature News Standard Article in Nature News & Comment
So, You can use id or xpath to retrieve the element text as follows:
Using id:
String s = driver.findElement(By.id("nav_20")).getText();
System.out.println(s);
Using xpath:
String s1 = driver.findElement(By.xpath("//span[#id='nav_20']")).getText();
System.out.println(s1);
css=a[href*='javascript:submitForm'] > span.p_textOutput
Try the above CSS Selector. I am sure it will work out.
Please Let me know is it working or NOT.

Resources