I want to show a ValidationSummary mcv3 with "alert-error" Bootstrap styling.
I'm using a Razor view, and I show model errors with this code:
#Html.ValidationSummary(true, "Errors: ")
It generates HTML code like this:
<div class="validation-summary-errors">
<span>Errors:</span>
<ul>
<li>Error 1</li>
<li>Error 2</li>
<li>Error 3</li>
</ul>
</div>
I tried with this too:
#Html.ValidationSummary(true, "Errors:", new { #class = "alert alert-error" })
and it works ok, but without the close button (X)
It generates HTML code like this:
<div class="validation-summary-errors alert alert-error">
<span>Errors:</span>
<ul>
<li>Error 1</li>
<li>Error 2</li>
<li>Error 3</li>
</ul>
</div>
but Bootstrap alert should have this button into the div:
<button type="button" class="close" data-dismiss="alert">×</button>
Can anyone help?
This Works! - Thanks Rick B
#if (ViewData.ModelState[""] != null && ViewData.ModelState[""].Errors.Count() > 0)
{
<div class="alert alert-error">
<a class="close" data-dismiss="alert">×</a>
<h5 class="alert-heading">Ingreso Incorrecto</h5>
#Html.ValidationSummary(true)
</div>
}
I also had to remove the class ".validation-summary-errors" from "site.css", because that style defines other font color and weight.
edited again
I misunderstood your question at first. I think the following is what you want:
#if (ViewData.ModelState[""] != null && ViewData.ModelState[""].Errors.Count > 0)
{
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">×</button>
#Html.ValidationSummary(true, "Errors: ")
</div>
}
This answer is based on RickB's one
Updated for the latest bootstrap ==>> alert-error doesn't exist in favor of alert-danger.
Works for all Validation Errors not only Key String.Empty ("")
For anyone using Bootstrap 3 and trying to get nice looking alerts:
if (ViewData.ModelState.Keys.Any(k=> ViewData.ModelState[k].Errors.Any())) {
<div class="alert alert-danger">
<button class="close" data-dismiss="alert" aria-hidden="true">×</button>
#Html.ValidationSummary(false, "Errors: ")
</div>
}
The solution provided by RickB works only on manually added errors on (String.Empty key) but not on those generated by ModelState (normally this gets triggered first via javascript but it's always a good practice to have a fallback if (for example) the Html.ValidationMessageFor is missing or many other situations.
Alternative solution. =)
#if (ViewData.ModelState.Any(x => x.Value.Errors.Any()))
{
// Bootstrap 2 = "alert-error", Bootstrap 3 and 4 = "alert-danger"
<div class="alert alert-danger alert-error">
<a class="close" data-dismiss="alert">×</a>
#Html.ValidationSummary(true, "Errors: ")
</div>
}
I did not like how the ValidationSummary rendered using a bullet list (unordered list). It had a lot of unnecessary space below the error list.
A solution to that issue - is simply to loop through the errors and render the errors how you want. I used paragraphs. 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>
}
The result, in my case, looks something like this:
#Html.ValidationSummary("", new { #class = "alert alert-danger" })
Consider writing an extension method to the HtmlHelper like:
public static class HtmlHelperExtensions
{
public static HtmlString ValidationSummaryBootstrap(this HtmlHelper htmlHelper)
{
if (htmlHelper == null)
{
throw new ArgumentNullException("htmlHelper");
}
if (htmlHelper.ViewData.ModelState.IsValid)
{
return new HtmlString(string.Empty);
}
return new HtmlString(
"<div class=\"alert alert-warning\">"
+ htmlHelper.ValidationSummary()
+ "</div>");
}
}
Then you just need to fit the ul-li styling in your stylesheet.
In MVC 5, ViewData.ModelState[""] always returned a null value. I had to resort to the IsValid command.
if (!ViewData.ModelState.IsValid)
{
<div class="alert alert-danger">
<a class="close" data-dismiss="alert">×</a>
<strong>Validation Errors</strong>
#Html.ValidationSummary()
</div>
}
I took a slightly different route: using JQuery to hook into the form submit:
$('form').each(function() {
var theForm = $(this);
theForm.submit(function() {
if ($(this).valid()) {
if ($(this).find('.validation-summary-valid').length) {
$('.validation-summary-errors').hide();
}
} else {
if ($(this).find('.validation-summary-errors').length) {
$('.validation-summary-errors')
.addClass('alert alert-error')
.prepend('<p><strong>Validation Exceptions:</strong></p>');
}
}
});
});
I have this set inside a self-executing javascript module so that it hooks onto any validation summaries that I create.
HTH
Chuck
You can use jquery:
$(function(){
$('.validation-summary-errors.alert.alert-error.alert-block').each(function () {
$(this).prepend('<button type="button" class="close" data-dismiss="alert">×</button>');
});
});
It is looking for every div containing given error classes from bootstrap and writing html at beginning of the div. I am adding .alert-block class as the bootstrap page says:
For longer messages, increase the padding on the top and bottom of the
alert wrapper by adding .alert-block.
This solution uses Sass to make it work but you could achieve the same thing with basic css. To make this work with client side validation we cant rely on checking the ModelState since that assumes a postback has occurred. The out-of-the-box mvc client side validation already makes things visible at the right time so let it do its thing and simply style the list items in the validation summary to render like bootstrap alerts.
Razor markup:
#Html.ValidationSummary(false, null, new { #class = "validation-summary-errors-alerts" })
Sass
.validation-summary-errors-alerts{
ul{
margin: 0;
list-style: none;
li{
#extend .alert;
#extend .alert-danger;
}
}}
The css that produced for my project looked like this - yours will be different:
.validation-summary-errors-alerts ul li {
min-height: 10px;
padding: 15px 20px 15px 62px;
position: relative;
border: 1px solid #ca972b;
color: #bb7629;
background-color: #fedc50;
font-family: Arial;
font-size: 13px;
font-weight: bold;
text-shadow: none;}
Based on the answers here:
#if (!ViewData.ModelState.IsValid)
{
<div class="alert alert-danger">
<button type="button" class="close" data-dismiss="alert">×</button>
#Html.ValidationSummary(false, "Errors: ")
</div>
}
(I'm using Bootstrap 4)
Alternative solution with pure javascript (jQuery). I'm working with MVC4 + Bootstrap3 but it works perfect for you.
$(function () {
$(".validation-summary-errors").addClass('alert alert-danger');
$(".validation-summary-errors").prepend('<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>')
});
If you don't want to write server side logic then is a nice alternative solution.
TwitterBootstrapMVC takes care of this one with just one line:
#Html.Bootstrap().ValidationSummary()
Important, to assure that it behaves the same during the server side and client side (unobtrissive) validation, you need to include a javaScript file that takes care of that.
You can customize your Validation helper with extension methods however you see fit.
Disclaimer: I'm the author of TwitterBootstrapMVC. Using it with Bootstrap 3 requires a license.
Expanding upon Daniel Björk's solution you can include a little script to adjust the CSS included with ValidationSummary() output. The resulting bootstrap alert was showing a rendering issue until I removed the validation-summary-errors class.
#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");
</script>
You can also easily give a bootstrap highlight to fields with errors. See http://chadkuehn.com/convert-razor-validation-summary-into-bootstrap-alert/
To achieve the same in bootstrap 4, use the following:
#if (ViewData.ModelState[""] != null && ViewData.ModelState[""].Errors.Count() > 0)
{
<div class="col-auto alert alert-danger" role="alert">
#Html.ValidationSummary(true)
</div>
}
If it needs to work with clientside javascript I suggests doing this:
.validation-summary-valid {
display: none;
}
You still can assign the bootstrap class
#Html.ValidationSummary(null, new {#class= "alert alert-danger" })
but it will only show when you have actual errors.
Related
I'm new to aurelia. I'm looking to find the best method for adding classes on click events.
I simply want to click approve or request information, and then add a class to the corresponding "contact card". This class would change the background color.
I know it's probably simple, but I thought I'd look here for the best method.
Here's an image to what I've got:
Apologies for the wait, work has been a bit busy.
This is my first time posting on S.O., so I apologize for any expectations I'm not meeting.
<div class="col-sm-4">
<button class="btn btn-success col-sm-12" click.delegate="goodBoi()">
approve contact
</button>
</div>
<div class="col-sm-4">
<button class="btn btn col-sm-12" click.delegate="requestContact()">
request information
</button>
</div>
</div>
the element to be changed is named "list-group-item", containing the
contact's details(code shown above).
<template>
<div class="contact-list">
<ul class="list-group">
<li repeat.for="contact of contacts" class="list-group-item ${contact.id === $parent.selectedId ? 'active' : ''}">
<a route-href="route: contacts; params.bind: {id:contact.id}" click.delegate="$parent.select(contact)">
<h4>${contact.firstName} ${contact.lastName}</h4>
<p>${contact.company}</p>
<p>${contact.email}</p>
<h6>${contact.approval}</h6>
</a>
<a route-href="route: contacts; params.bind: {id:contact.id}">
<p>${contact.phoneNumber}</p>
</a>
</li>
</ul>
</div>
goodBoi() {
let result = confirm("Are you sure you want to confirm this contact?");
if (result === true) {
var standingShell = document.getElementsByClassName("list-group-item");
//im hoping here I would add a class to the new variable//
this.contact.approval = 'approved';
this.save();
}
}
//confirms contact, changing color of approved contact//
//same thing here, just plan to give it a different color//
requestContact() {
let contactRequestText = "request sent to contact";
this.routeConfig.navModel.setTitle(this.contact.approval = contactRequestText);
this.ea.publish(new ContactUpdated(this.contact));
}
There are many ways to set a CSS-class using Aurelia. Following I prepared an example gist:
Template:
<template>
<h1>${message}</h1>
<div class="form-group ${clicked ? 'red' : 'blue'}" style="width: 100px; height: 100px;">
</div>
<div class="form-group">
<button click.delegate="save()">
Click me
</button>
</div>
</template>
And the code class:
#autoinject
export class App {
#bindable clicked = false;
save(){
this.clicked = true;
}
}
https://gist.run/?id=425993b04a977466fa685758389aa2b4
But there are other, cleaner ways:
using ref in a custom element.
custom attributes.
Include jQuery for using e.g. $('#myelement').addClass()
I have a list :
$scope.list = ["test/test1/test2/test3","test3/test5/test6"];
I would like to apply bold style to / characters when displaying the list :
<div ng-repeat="path in list">
<p style="font-weight:bold">{{path}}</p>
</div>
Do you have any ideas how can I achieve this ?
Fiddle
you can do it simply with str.replace http://jsfiddle.net/k18vgtvw/
<p style="font-weight:bold" ng-bind-html-unsafe="csc(path)"></p>
controller
$scope.csc = function(path) {
return path.replace(/\//g, "<span style='color:red'>/</span>");
}
There are a number of ways to do this. First I'd add a function to your controller, let's say it's called boldSlashes.
function boldSlashes(path) {
return path.replace("/","<b>/</b>")
}
Then change your html to be:
<div ng-repeat="path in list" ng-bind-html>
boldSlashes({{path}})
</div>
The ng-bind-html tells angular to treat the contents as html and not escape it.
You also have to inject ngSanitize into you module in order to use ng-bind-html.
So wherever you create your module, add ngSanitize to the dependencies like:
angular.module('myApp',[ngSanitize])
I'm not sure if this is what you are trying to do but I separated out individual elements. Also the jsfiddle font the bold font looks exactly the same on the / character.
http://jsfiddle.net/3a2duqg4/
1. Updated the view to a list
2. Changed the array to have an individual item per section
3. Added styles to the "/" and realized the font bold property with the fiddle default font didn't look any different.
<div ng-controller="MyCtrl">
<ul>
<li class="list" ng-repeat="path in list">{{path}} <span>/</span></li>
</ul>
</div>
Added the items to a list rather than a paragraph and added some styles. I updated your array to have one value per array item as well.
Let me know if this helps! :)
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.list = ["test/test1/test2/test3","test3/test5/test6"];
$scope.updateString = function(s) {
return s.replace(/\//g, '<span class="bold">/</span>');
};
}
.bold {
font-weight: bold;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<div ng-repeat="path in list">
<p ng-bind-html-unsafe="updateString(path)"></p>
</div>
</div>
</div>
I was originally having problems with the below JS smooth scroll as it made any real links rather then #location stop working.
$('.navbar-nav > li').click(function(event) {
event.preventDefault();
var target = $(this).find('>a').prop('hash');
$('html, body').animate({
scrollTop: $(target).offset().top
}, 500);
});
So I changed it to
$(document).ready(function(){
$('a[href*=#]').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'')
&& location.hostname == this.hostname) {
var $target = $(this.hash);
$target = $target.length && $target
|| $('[name=' + this.hash.slice(1) +']');
if ($target.length) {
var targetOffset = $target.offset().top;
$('html,body')
.animate({scrollTop: targetOffset}, 1200);
return false;
}
}
});
});
Which sorted the original problem of being unable to add a working "blog" link in the navbar however it has now rendered the left and right (next and prev) carousel buttons not working.
I would be grateful if someone can help me out with this as it is driving me crazy.
The html for the carousel is as follows
<section id="main-slider" class="carousel">
<div class="carousel-inner">
<div class="item active">
<div class="container">
<div class="carousel-content">
<h1>Responsive Website Design</h1>
<p class="lead">With 20% of all website traffic in the UK coming from tablets and smart phones then never before has it been a better time to have a responsive website.</p>
</div>
</div>
</div><!--/.item-->
<div class="item">
<div class="container">
<div class="carousel-content">
<h1>Free Consultation</h1>
<p class="lead">I understand every business has different needs so we can discuss what it is your want to achieve and using my expert advice make it a reality.</p>
</div>
</div>
</div><!--/.item-->
<div class="item">
<div class="container">
<div class="carousel-content">
<h1>Built to be SEO/Google Friendly</h1>
<p class="lead">Having a website built is the first step but next you need to put it in front of your target audience. On site SEO is where it all begins.</p>
</div>
</div>
</div><!--/.item-->
</div><!--/.carousel-inner-->
<a class="prev" href="#main-slider" data-slide="prev"><i class="icon-angle-left"></i></a>
<a class="next" href="#main-slider" data-slide="next"><i class="icon-angle-right"></i></a>
</section><!--/#main-slider-->
First of all, the answers above are correct. I just wanted to spell it out a little clearer for anyone needing help.
The code that needs to be updated is the SmoothScroll function itself. You will need to know the ID of the carousel from your bootstrap page. Just add the carousel ID to the not().click function and it will work like a charm. Here is an example of what I did. The change was made on the third line of code, where you see the carousel ID#.
<script>
$(function() {
$('a[href*=#]:not([href=#carousel-299058])').click(function() {
if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
var target = $(this.hash);
target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
if (target.length) {
$('html,body').animate({
scrollTop: target.offset().top - 70
}, 500);
return false;
}
}
});
});
</script>
Try replacing this:
$('a[href*=#]:not([href=#])').click(function() {
with:
$('a[href*=#]:not([href=#media])').click(function () {
Happy coding!
I was using the smooth scrolling javascript everyone uses and having the same issue, like all obedient little developers out there I was using #myCarousel:
<a class="right carousel-control" href="#myCarousel" data-slide="next">
and as soon as I changed [href=media] to [href=myCarousel] my Bootstrap carousel controls started working again.
I had this issue recently and my solution was to use a class on each link as opposed to the href attribute selectors within the jQuery function.
This does mean a little extra HTML mark-up but I felt it was more robust and causes less interference with additional scripts that may be added within your project.
So this:
$('a[href*=#]:not([href=#])').click(function() {
Becomes this:
$('.your-class-name').click(function() {
And any smooth scrolling links you add to your page will become:
Link
And scroll to:
<div id="section">... Content ...</div>
Dont forget to add : \\. It is necessary to add it since the latest version of JQUERY.
$('a[href*=\\#]:not([href=\\#carousel-299058])').click(function() {
I need a help. I have this structure
<div class="buttons">
<p onclick="function1('param1')">button1</p>
<p onclick="function2('param2')">button2</p>
<p onclick="function3('param3')">button3</p>
</div>
This code works perfecty, but in addition I need add class="active" to current selected button which I can not do. The following code does not work.
$(document).ready(function() {
$('.buttons').click(function(){
if($(this).hasClass('active')){
return false;
}
else{
$('.buttons > p').removeClass('active');
$(this).addClass('active');
}
});
})
Can anyone say how to solve this problem?
You have a typo in
<div class="buutons">
it should be
<div class="buttons">
Also
<p onclick="function3('param3')>button3</p>
should be
<p onclick="function3('param3')">button3</p>
JSFiddle is here.
remove the onclick attribute on the p elements, it will overwrite the listener you registered in your js code, register it in the js code instead.
change you code, add "> p" in your first selector:
$(document).ready(function() {
$('.buttons > p').click(function(){
if($(this).hasClass('active')){
return false;
}
else{
$('.buttons > p').removeClass('active');
$(this).addClass('active');
}
});
})
I created in blog spot a new page for a gallery with a menu, the result is good but there is so much space between the buttons, and a big gap in the top of the page, when I try <b> or <p> It wont go, I also tried to minimise the space with another script but the result was no space but unclickable buttons, and always when I success deleting spaces, the buttons wont work ! Please help me ! (It works on dreamweaver perfectly but not on Blogger !
This is the code :
<p> <p><b:include data='blog' name='all-head-content'/></p>
<p><style type="text/css">
.menutitle{
cursor:pointer;
<span style="margin-bottom: 5px"><br>;
background-color:#000000 ;
color:#FFF;
width:140px;
padding:2px;
text-align:center;
font-weight:bold;
/*/*/border:0px solid #000000;/* */
}</p>
.submenu{
margin-bottom: 0.5em;
}
</style> </p>
</b:if>
<p><script type="text/javascript">
var persistmenu="yes" //"yes" or "no". Make sure each SPAN content contains an incrementing ID starting at 1 (id="sub1", id="sub2", etc)
var persisttype="sitewide" //enter "sitewide" for menu to persist across site, "local" for this page only
if (document.getElementById){ //DynamicDrive.com change
document.write('<style type="text/css">\n')
document.write('.submenu{display: none;}\n')
document.write('</style>\n')
}
function SwitchMenu(obj){
if(document.getElementById){
var el = document.getElementById(obj);
var ar = document.getElementById("masterdiv").getElementsByTagName("span"); //DynamicDrive.com change
if(el.style.display != "block"){ //DynamicDrive.com change
for (var i=0; i<ar.length; i++){
if (ar[i].className=="submenu") //DynamicDrive.com change
ar[i].style.display = "none";
}
el.style.display = "block";
}else{
el.style.display = "none";
}
}
}
function get_cookie(Name) {
var search = Name + "="
var returnvalue = "";
if (document.cookie.length > 0) {
offset = document.cookie.indexOf(search)
if (offset != -1) {
offset += search.length
end = document.cookie.indexOf(";", offset);
if (end == -1) end = document.cookie.length;
returnvalue=unescape(document.cookie.substring(offset, end))
}
}
return returnvalue;
}
function onloadfunction(){
if (persistmenu=="yes"){
var cookiename=(persisttype=="sitewide")? "switchmenu" : window.location.pathname
var cookievalue=get_cookie(cookiename)
if (cookievalue!="")
document.getElementById(cookievalue).style.display="block"
}
}
function savemenustate(){
var inc=1, blockid=""
while (document.getElementById("sub"+inc)){
if (document.getElementById("sub"+inc).style.display=="block"){
blockid="sub"+inc
break
}
inc++
}
var cookiename=(persisttype=="sitewide")? "switchmenu" : window.location.pathname
var cookievalue=(persisttype=="sitewide")? blockid+";path=/" : blockid
document.cookie=cookiename+"="+cookievalue
}
<p>if (window.addEventListener)
window.addEventListener("load", onloadfunction, false)
else if (window.attachEvent)
window.attachEvent("onload", onloadfunction)
else if (document.getElementById)
window.onload=onloadfunction
if (persistmenu=="yes" && document.getElementById)
window.onunload=savemenustate </p>
</script></p>
<!-- Keep all menus within masterdiv-->
<div id="masterdiv">
<div class="menutitle" onclick="SwitchMenu('sub1')">Dior</div>
<span class="submenu" id="sub1">
<p><div id="PictoBrowser110620155241">Get the flash player here: http://www.adobe.com/flashplayer</div><script type="text/javascript" src="http://www.db798.com/pictobrowser/swfobject.js"></script><script type="text/javascript"> var so = new SWFObject("http://www.db798.com/pictobrowser.swf", "PictoBrowser", "500", "650", "8", "#000000"); so.addVariable("source", "sets"); so.addVariable("names", "Scheisse"); so.addVariable("userName", "ScheisseMag"); so.addVariable("userId", "64286522#N04"); so.addVariable("ids", "72157626880953125"); so.addVariable("titles", "on"); so.addVariable("displayNotes", "on"); so.addVariable("thumbAutoHide", "off"); so.addVariable("imageSize", "medium"); so.addVariable("vAlign", "mid"); so.addVariable("vertOffset", "0"); so.addVariable("colorHexVar", "f"); so.addVariable("initialScale", "on"); so.addVariable("bgAlpha", "8"); so.write("PictoBrowser110620155241"); </script>
</span>
<div class="menutitle" onclick="SwitchMenu('sub2')">FAQ/Help</div>
<span class="submenu" id="sub2">
- Usage Terms<br>
- DHTML FAQs<br>
- Scripts FAQs</span>
<div class="menutitle" onclick="SwitchMenu('sub3')">Help Forum</div>
<span class="submenu" id="sub3">
- Coding Forums<br></span>
<div class="menutitle" onclick="SwitchMenu('sub4')">Cool Links</div>
<span class="submenu" id="sub4">
- JavaScript Kit<br>
- Freewarejava<br>
- Cool Text<br>
- Google.com
</span></p></div> </p>
I'm assuming you're using Firefox, because it doesn't seem to work the same using other browsers..
the problem is the space between eich
bouton like between Dior and Faq/help
and help forum, they are meant to be
attached to each other
I'll start by saying that I'm not familiar with Blogger.
Your HTML:
<div class="menutitle" onclick="SwitchMenu('sub2')">FAQ/Help</div>
<span class="submenu" id="sub2">..</span>
<div class="menutitle" onclick="SwitchMenu('sub3')">
What you get if you View Source on your page:
<div class="menutitle" onclick="SwitchMenu('sub2')">FAQ/Help</div>
<span class="submenu" id="sub2">..</span><br /> <!-- extra br! -->
<div class="menutitle" onclick="SwitchMenu('sub3')">
Those frequent extra <br />s are the main problem. There are lots of them. You need to prevent them from being inserted. Perhaps removing the whitespace in your HTML will help? Like this:
<div class="menutitle" onclick="SwitchMenu('sub2')">FAQ/Help</div>
<span class="submenu" id="sub2">..</span><div class="menutitle" onclick="SwitchMenu('sub3')">
also the gap between the Title of the
page and those menus !
You need to get rid of many instances of <p> and </p> that are wrapped around everything, including <script>s, for some reason..
Also, you have the same problem with <br />s being magically inserted. Again, compare your HTML to what comes out when you use View Source in your browser.
After removing those extraneous <p> and </p> and <br /> using Firebug (just to test), this was the result: