Apply Twitter Bootstrap Validation Style and Message to ASP.NET MVC validation - css

How can I integrate ASP.NET MVC unobtrusive validation and Twitter Bootstrap? I want to have all those validation messages and styles appropriately.

A nice way of handling this if you're using Bootstrap 2 is...
Add this to your _Layout.cshtml:
<script type="text/javascript">
jQuery.validator.setDefaults({
highlight: function (element, errorClass, validClass) {
if (element.type === 'radio') {
this.findByName(element.name).addClass(errorClass).removeClass(validClass);
} else {
$(element).addClass(errorClass).removeClass(validClass);
$(element).closest('.control-group').removeClass('success').addClass('error');
}
},
unhighlight: function (element, errorClass, validClass) {
if (element.type === 'radio') {
this.findByName(element.name).removeClass(errorClass).addClass(validClass);
} else {
$(element).removeClass(errorClass).addClass(validClass);
$(element).closest('.control-group').removeClass('error').addClass('success');
}
}
});
$(function () {
$("span.field-validation-valid, span.field-validation-error").addClass('help-inline');
$("div.control-group").has("span.field-validation-error").addClass('error');
$("div.validation-summary-errors").has("li:visible").addClass("alert alert-block alert-error");
});
</script>
These are the posts where I found the code pieces above:
Integrating Bootstrap Error styling with MVC’s Unobtrusive Error Validation
Twitter Bootstrap validation styles with ASP.NET MVC
MVC Twitter Bootstrap unobtrusive error handling
UPDATE
Right now I needed to do the same when using Bootstrap 3. Here's the modifications necessary since the class names changed:
<script type="text/javascript">
jQuery.validator.setDefaults({
highlight: function (element, errorClass, validClass)
{
if (element.type === 'radio')
{
this.findByName(element.name).addClass(errorClass).removeClass(validClass);
} else
{
$(element).addClass(errorClass).removeClass(validClass);
$(element).closest('.form-group').removeClass('has-success').addClass('has-error');
}
},
unhighlight: function (element, errorClass, validClass)
{
if (element.type === 'radio')
{
this.findByName(element.name).removeClass(errorClass).addClass(validClass);
} else
{
$(element).removeClass(errorClass).addClass(validClass);
$(element).closest('.form-group').removeClass('has-error').addClass('has-success');
}
}
});
$(function () {
$("span.field-validation-valid, span.field-validation-error").addClass('help-block');
$("div.form-group").has("span.field-validation-error").addClass('has-error');
$("div.validation-summary-errors").has("li:visible").addClass("alert alert-block alert-danger");
});
</script>

Copy the css of the validators in your css file and change the color accordinlgly.
Something like this should do
.field-validation-error {
color: #b94a48;
display: inline-block;
*display: inline;
padding-left: 5px;
vertical-align: middle;
*zoom: 1;
}
.field-validation-valid {
display: none;
}
.input-validation-error {
/*
border: 1px solid #ff0000;
background-color: #ffeeee;
*/
color: #b94a48;
border-color: #b94a48;
}
.input-validation-error:focus {
border-color: #953b39;
-webkit-box-shadow: 0 0 6px #d59392;
-moz-box-shadow: 0 0 6px #d59392;
box-shadow: 0 0 6px #d59392;
}
.validation-summary-errors {
/*font-weight: bold;*/
color: #b94a48;
}
.validation-summary-valid {
display: none;
}

I suggest to include Bootstrapper in less format and do the same thing as Iridio suggested but in .less.
That way you could have something like:
.validation-summary-errors
{
.alert();
.alert-error();
}
.field-validation-error
{
.label();
.label-important();
}
so when bootstrapper will change you'll pick up the changes automatically.
Regular styles that handle visibility from MVC default Site.css will stay in place and handle visibility.

Why not just use css !important and call it a day:
/* Styles for validation helpers
-----------------------------------------------------------*/
.field-validation-error {
color: #f00 !important;
}
.field-validation-valid {
display: none;
}
.input-validation-error {
border: 1px solid #f00 !important;
background-color: #fee !important;
}
.validation-summary-errors {
font-weight: bold;
color: #f00;
}
.validation-summary-valid {
display: none;
}

On Bootstrap 3 you have to add:
.validation-summary-errors
{
.alert();
.alert-danger();
}
.field-validation-error
{
.label();
.label-danger();
}
you'll see something like that:

For the ValidationSummary, you can use the overload that allows you to specify htmlAttributes. This allows you to set it to use the Twitter Bootstrap alert css styles.
#Html.ValidationSummary(string.Empty, new { #class = "alert alert-danger" })
A similar overload exists for the ValidationMessage and ValidationMessageFor helper methods.

You can integrate MVC3 validation with Bootstrap framework by adding the following javascript to your page (View)
<script>
$(document).ready(function () {
/* Bootstrap Fix */
$.validator.setDefaults({
highlight: function (element) {
$(element).closest("div.control-group").addClass("error");
},
unhighlight: function (element) {
$(element).closest("div.control-group").removeClass("error");
}
});
var current_div;
$(".editor-label, .editor-field").each(function () {
var $this = $(this);
if ($this.hasClass("editor-label")) {
current_div = $('<div class="control-group"></div>').insertBefore(this);
}
current_div.append(this);
});
$(".editor-label").each(function () {
$(this).contents().unwrap();
});
$(".editor-field").each(function () {
$(this).addClass("controls");
$(this).removeClass("editor-field");
});
$("label").each(function () {
$(this).addClass("control-label");
});
$("span.field-validation-valid, span.field-validation-error").each(function () {
$(this).addClass("help-inline");
});
$("form").each(function () {
$(this).addClass("form-horizontal");
$(this).find("div.control-group").each(function () {
if ($(this).find("span.field-validation-error").length > 0) {
$(this).addClass("error");
}
});
});
});
</script>
Besides, on the Views (for example "Create.cshtml") make sure that the fields in the form are formatted as the following...
<div class="editor-label">
#Html.LabelFor(Function(model) model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(Function(model) model.Name)
#Html.ValidationMessageFor(Function(model) model.Name)
</div>

For those using Bootstrap 3, the css classes have changed and the solutions above need modifications to work with Bootstrap 3. I have used the following with success with MVC 4 and Bootstrap 3. See this SO thread for more:
$(function () {
// any validation summary items should be encapsulated by a class alert and alert-danger
$('.validation-summary-errors').each(function () {
$(this).addClass('alert');
$(this).addClass('alert-danger');
});
// update validation fields on submission of form
$('form').submit(function () {
if ($(this).valid()) {
$(this).find('div.control-group').each(function () {
if ($(this).find('span.field-validation-error').length == 0) {
$(this).removeClass('has-error');
$(this).addClass('has-success');
}
});
}
else {
$(this).find('div.control-group').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).removeClass('has-success');
$(this).addClass('has-error');
}
});
$('.validation-summary-errors').each(function () {
if ($(this).hasClass('alert-danger') == false) {
$(this).addClass('alert');
$(this).addClass('alert-danger');
}
});
}
});
// check each form-group for errors on ready
$('form').each(function () {
$(this).find('div.form-group').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).addClass('has-error');
}
});
});
});
var page = function () {
//Update the validator
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".form-group").addClass("has-error");
$(element).closest(".form-group").removeClass("has-success");
},
unhighlight: function (element) {
$(element).closest(".form-group").removeClass("has-error");
$(element).closest(".form-group").addClass("has-success");
}
});
}();

You can add a few classes to your Site.css file:
/* styles for validation helpers */
.field-validation-error {
color: #b94a48;
}
.field-validation-valid {
display: none;
}
input.input-validation-error {
border: 1px solid #b94a48;
}
select.input-validation-error {
border: 1px solid #b94a48;
}
input[type="checkbox"].input-validation-error {
border: 0 none;
}
.validation-summary-errors {
color: #b94a48;
}
.validation-summary-valid {
display: none;
}
FYI: http://weblogs.asp.net/jdanforth/form-validation-formatting-in-asp-net-mvc-5-and-bootstrap-3

This will convert ValidationSummary() to a boostrap alert. You can include a little script to remove unnecessary classes and give a highlight to fields with problems.
#if (ViewData.ModelState.Any(x => x.Value.Errors.Any())) {
<div class="alert alert-danger">
×
<h4>Validation Errors</h4>
#Html.ValidationSummary()
</div>
}
<script>
$(".validation-summary-errors").removeClass("validation-summary-errors");
$(".input-validation-error").removeClass("input-validation-error").parent().addClass("has-error");
</script>
See more information at http://chadkuehn.com/convert-razor-validation-summary-into-bootstrap-alert/

This is a neat solution that gives you more control over how the ValidationSummary renders errors to the view. The Unordered List it produced did not look right inside the alert. Therefore, I simply looped through the errors and rendered them how I wanted - using paragraphs in this case. For example:
#if (ViewData.ModelState.Any(x => x.Value.Errors.Any()))
{
<div class="alert alert-danger" role="alert">
<a class="close" data-dismiss="alert">×</a>
#foreach (var modelError in Html.ViewData.ModelState.SelectMany(keyValuePair => keyValuePair.Value.Errors))
{
<p>#modelError.ErrorMessage</p>
}
</div>
}
Which results in a neat Validation Summary Alert:

The following worked for me:
$(function () {
// any validation summary items should be encapsulated by a class alert and alert-danger
$('.validation-summary-errors').each(function () {
$(this).addClass('alert');
$(this).addClass('alert-danger');
});
// update validation fields on submission of form
$('form').submit(function () {
if ($(this).valid()) {
$(this).find('div.control-group').each(function () {
if ($(this).find('span.field-validation-error').length == 0) {
$(this).removeClass('has-error');
$(this).addClass('has-success');
}
});
}
else {
$(this).find('div.control-group').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).removeClass('has-success');
$(this).addClass('has-error');
}
});
$('.validation-summary-errors').each(function () {
if ($(this).hasClass('alert-danger') == false) {
$(this).addClass('alert');
$(this).addClass('alert-danger');
}
});
}
});
// check each form-group for errors on ready
$('form').each(function () {
$(this).find('div.form-group').each(function () {
if ($(this).find('span.field-validation-error').length > 0) {
$(this).addClass('has-error');
}
});
});
});
var page = function () {
//Update the validator
$.validator.setDefaults({
highlight: function (element) {
$(element).closest(".form-group").addClass("has-error");
$(element).closest(".form-group").removeClass("has-success");
},
unhighlight: function (element) {
$(element).closest(".form-group").removeClass("has-error");
$(element).closest(".form-group").addClass("has-success");
}
});
}();
Taken from http://www.benripley.com/development/javascript/asp-mvc-4-validation-with-bootstrap-3.

Related

How can I use data in css with Vue?

I want to design a button component with Vue.
When I get main props, how can I get in css --mainColor variable without setting inline-style? thanks.
<script>
import Vue from "vue";
export default Vue.extend({
name: "Button",
props: {
text: {
type: String,
default: ""
},
main: {
type: String,
default: "#10b981"
}
}
});
</script>
<style lang="scss" scoped>
.btn {
--mainColor: #10b981;
display: inline-block;
border: 1px solid var(--mainColor);
color: var(--mainColor);
&:hover {
background-color: var(--mainColor);
color: #fff;
}
}
</style>
I doubt that's possible. But you can run conditional logic in sass, like their official example:
$light-background: #f2ece4;
$light-text: #036;
$dark-background: #6b717f;
$dark-text: #d2e1dd;
#mixin theme-colors($light-theme: true) {
#if $light-theme {
background-color: $light-background;
color: $light-text;
} #else {
background-color: $dark-background;
color: $dark-text;
}
}
.banner {
#include theme-colors($light-theme: true);
body.dark & {
#include theme-colors($light-theme: false);
}
}
https://sass-lang.com/documentation/at-rules/control/if
This is super easy if using Vue3:
<template>
<h1>HELLO</h1>
</template>
<script>
export default {
data() {
return {
h1Color: "red",
};
},
};
</script>
<style>
h1 {
color: v-bind(h1Color);
}
</style>
For a more extensive guide - here
If using Vue2 I would suggest using the same approach as in Steven B's answer, here the ref

Make position: fixed behavior like sticky (for Vue2)

Position: sticky doesn't support by the most mobile browsers. But position: fixed is not that thing I need (because of fixed block overlaps content in the bottom of document).
I guess for jquery it will be easy to set static position for fixed block if we get bottom of document onscroll.
But for Vue2 I haven't any idea how to do the same. Give some advice please. Or maybe better solution exists.
As I mentioned in the comments, I'd recommend using a polyfill if at all possible. They will have put a lot of effort into getting it right. However, here is a simple take on how you might do it in Vue.
I have the application handle scroll events by putting the scrollY value into a data item. My sticky-top component calculates what its fixed top position would be, and if it's > 0, it uses it. The widget is position: relative.
new Vue({
el: '#app',
data: {
scrollY: null
},
mounted() {
window.addEventListener('scroll', (event) => {
this.scrollY = Math.round(window.scrollY);
});
},
components: {
stickyTop: {
template: '<div class="a-box" :style="myStyle"></div>',
props: ['top', 'scrollY'],
data() {
return {
myStyle: {},
originalTop: 0
}
},
mounted() {
this.originalTop = this.$el.getBoundingClientRect().top;
},
watch: {
scrollY(newValue) {
const rect = this.$el.getBoundingClientRect();
const newTop = this.scrollY + +this.top - this.originalTop;
if (newTop > 0) {
this.$set(this.myStyle, 'top', `${newTop}px`);
} else {
this.$delete(this.myStyle, 'top');
}
}
}
}
}
});
#app {
height: 1200px;
}
.spacer {
height: 80px;
}
.a-box {
display: inline-block;
height: 5rem;
width: 5rem;
border: 2px solid blue;
position: relative;
}
<script src="//unpkg.com/vue#latest/dist/vue.js"></script>
<div id="app">
<div class="spacer"></div>
<div class="a-box"></div>
<sticky-top top="20" :scroll-y="scrollY"></sticky-top>
<div class="a-box"></div>
</div>
This seem to work for me
...
<header
ref="header"
class="header-container"
:class="{ 'header-container--sticky': isHeaderSticky }"
>
...
...
data() {
return{
scrollY: null,
headerTop: 0,
isHeaderSticky: false,
}
},
mounted() {
window.addEventListener('load', () => {
window.addEventListener('scroll', () => {
this.scrollY = Math.round(window.scrollY);
});
this.headerTop = this.$refs.header.getBoundingClientRect().top;
});
},
watch: {
scrollY(newValue) {
if (newValue > this.headerTop) {
this.isHeaderSticky = true;
} else {
this.isHeaderSticky = false;
}
}
}
...
...
.header-container {
&--sticky {
position: sticky;
top: 0;
z-index: 9999;
}
}
...

React did not render new css style

This is my code logic, When user click the box , I will set the state active to true
and getCssStyle() will return drag-and-resize-box-text clicked
and then the background image(T) should disappear
class Box extends Component {
constructor(props) {
super(props);
this.state = {
active: false,
}
}
// decide which style to be used
getCssStyle = (type) => {
switch (type) {
case 'text':
if (this.state.active) {
console.log("AAA")
return 'drag-and-resize-box-text clicked'
} else {
console.log("BBB")
return 'drag-and-resize-box-text';
}
// break;
default:
return '';
}
}
onClick = () => {
this.setState({active: true});
}
render() {
return (
<div className={this.getCssStyle(boxType)} >
{this.boxFillContent()}
</div>
</div>
);
}
}
The dev tools show the background image is delete, but the page is still show the image
What's wrong with this??
css
.drag-and-resize-box-text{
border: dashed 3px LightSeaGreen;
background: url(../images/bottom/text_normal.png) no-repeat;
background-position:center;
width: inherit;
height: inherit;
}
.drag-and-resize-box-text.clicked{
border: dashed 3px LightSeaGreen;
/*background: url(../images/bottom/text_normal.png) no-repeat;*/
background-position:center;
width: inherit;
height: inherit;
}
.drag-and-resize-box-text.clicked should have background: none.
Also your code could be made much simpler by using
<div className={this.state.active ? 'drag-and-resize-box-text clicked' : 'drag-and-resize-box-text'} >
{this.boxFillContent()}
</div>

Hghlighted field with red border in Wordpress Contact Form 7

I want to get this effect http://jquery.bassistance.de/validate/demo/ by Wordpress Contact Form 7.
I set in css
.wpcf7-not-valid{
border:1px solid #d73333!important;
}
But when I insert value into the field the red border do not disappear.
Got a good solution. In wp-content\plugins\contact-form-7\includes\js\scripts.js
Changed
$.fn.wpcf7NotValidTip = function(message) {
return this.each(function() {
var into = $(this);
into.append('<span class="wpcf7-not-valid-tip">' + message + '</span>');
$('span.wpcf7-not-valid-tip').mouseover(function() {
$(this).fadeOut('fast');
});
into.find(':input').mouseover(function() {
into.find('.wpcf7-not-valid-tip').not(':hidden').fadeOut('fast');
});
into.find(':input').focus(function() {
into.find('.wpcf7-not-valid-tip').not(':hidden').fadeOut('fast');
});
});
};
to this code
$.fn.wpcf7NotValidTip = function(message) {
return this.each(function() {
var into = $(this);
$theParent = into.parent("span");
$parentInp = $theParent.parent("input");
into.find(':input').css('border-color', '#d73333');
into.find(':input').mouseover(function() {
into.find(':input').css('border-color','#cccccc');
});
into.find(':input').focus(function() {
into.find(':input').css('border-color','#cccccc');
});
});
};
.wpcf7-validation-errors, .wpcf7-mail-sent-ng {
padding: 5px;
color: #E68B8B;
background-color: #FDF5F8 !important;
border: 1px solid #FDE2E2 !important;
width: 518px !important;
}
There is no universal solution because it all depends on how you styled your form
Anyway you can try use something like that:
span .wpcf7-not-valid {
border: 1px solid #ff0000 !important;
}
Note: using !important is never the best way to do anything with css

Overriding jquery ui after addClass

I have a div which contains a list.
Its CSS:
#ResultsText
{
color: #696969;
text-align: right;
vertical-align: top;
}
In the JS file:
$("li.ResultParagraph").mouseover(function () {
$(this).addClass("ui-state-hover");
}).mouseout(function () {
$(this).removeClass("ui-state-hover");
});
$('.ui-state-hover').css("font-weight", "normal");
but still I see the hover text in bold.
Any suggestions?
You should do like this(or switch "bold" with "normal")
$("li.ResultParagraph").mouseover(function () {
$(this).addClass("ui-state-hover").css("font-weight", "bold");
}).mouseout(function () {
$(this).removeClass("ui-state-hover").css("font-weight", "normal");
});
DEMO

Resources