Custom data annotation to hide property based on another's value - c#

Having a nightmare figuring this out and I am now flat against the brick wall
Using MVC framework I'm building essentially a simple form.
I'm keeping the view as simple as possible and using just editorForModel()
So within this forms model I'm using data annotations to add some more customisations to the properties.
I would like to create a custom data annotation, one that will hide the property it has been placed against based on the value of another property.
E.g
I have a drop down with yes or no.
And a field for name.
When the drop down is no it hides the name field in the form.
I can achieve this with JS but it would be nice going forward to have this as a simple data annotation for the model.
E.g [HideField("dropdown", "no")]
Thanks in advance

You're going to want to handle this on the client side, not server side (using an Attribute).
If you're already using jQuery, something like this would do. Here is the jsFiddle.
$(function () {
var dropdown = $('#dropdown').change(function (event) {
if ($(this).val() == "no") {
$('#fieldToHide').hide();
} else {
$('#fieldToHide').show();
}
});
});
The reason you want to do it on the client side is pretty simple, any other method would require a post back with every change of the dropdown to check the value..
** EDIT **
From comment:
Is it possible to inject this JavaScript into the page... ...Rather than having the essentially the same script duplicated on each page
This could be rewritten, a little more generic, so it could be reused on different pages. Add it to yoursite.js (which you should already have..) and then simply wire it up on each page as desired. Updated jsFiddle.
Site.JS
function hideIf(selectField, hideField, hideValue) {
$(selectField).change(function (event) {
if ($(this).val() == hideValue) {
$(hideField).hide();
} else {
$(hideField).show();
}
});
}
And then in each page you want to use it, wire it up like this:
$(function () {
hideIf("#dropdown", "#fieldToHide", "no");
});
This way you could make multiple calls to hideIf on different select fields without rewriting the script above..

Related

Edit ViewBag based on dropdownlist selected

i have some form with dropdownlist, i want when i select that dropdownlist, the value is passed into controller without page reload, and then change that form based on value pased, without page reload too. I have search for reference like ajax, etc, but none works for me. Please help,
I have two action in controller with that view, one to show the form and one to process httppost with that form, do i have to make one more for this?
Thankyou
What you could do is use an Ajax:
-It's be better to use MVC API controller. (Read about Api controller)
-If you want to use the controller then add the path to the routing table
Example:
-Your dropdown list onSelection/Change should trigger your JavaScript function.
-Your javaScript function should contain the following:
-(Read about how to pass json Objects around).
var json = { //You will use json to send your selected value to your controller or api
selectedValue: SelectedValue
}
$.post("//Path for controller/FolderName/Controller/MethodName", json, function (data) {
//Code after data received
if(data.success == true){//display message etc)
});
Alternative:
Create another page with the form and use razor to edit the form.
You could try the $get function in Jquery.
On change event of the drop down you can call a javaScript method to use $get:
Example
$.get(url, function (data) {
$YourDiv.html(data); //re-insert the form into the page
}
https://api.jquery.com/jquery.get/

How to validate server side code in Javascript

I am getting some value from server , if the value is false i need to show alert message on UI without refreshing or postbacking the page.
What i am doing currently is i get the value from server i declare one hidden control and store that value in hidden control and in aspx page i write one JS method to check if that value is false show the alert message, but the problem is i have to do this on click on a button which is present in code behind
so as soon as i click on that button JS code gets executed before i get value from server.
function fnvalidation() {
if (document.getElementById("<%=hdnCtrl.ClientID%>").value == false) {
alert('Please submit it again');
return false;
}
}
On page load i am registering like this :
btnSave.Attributes.Add("onclick", "return fnvalidation()");
C# Code :
bValidate = CommonUtility.ValidateOutput();
hdnCtrl.Value = bValidate.ToString();//Storing value in hidden variable
if(bvalidate == false)
{
//Call javascript method fnvalidation
}
How to call this JS method correctly when value is false coming from server ?
Thanks.
If your page needs to fetch data from the server without refreshing the page, then you need to use AJAX. Which comes down to two things:
Create an AJAX endpoint in server-side code.
Consume that AJAX endpoint from client-side code.
The server-side code likely has several options. HTTP Handlers, empty ASPX pages which clear and response and set a new content type, maybe even Web Methods? It's been a long time since I've used WebForms, so I'm not 100% sure what the recommended approach is right now. But I think Web Methods are what you're looking for. So your code-behind would have something like this:
public partial class MyPage : Page
{
[WebMethod]
public static string GetValue()
{
return "some value";
}
}
Then, assuming you're using jQuery for example, you would call that endpoint from your client-side code:
$.ajax({
type: "POST",
url: "MyPage.aspx/GetValue"
}).done(function (data) {
// respond to the value in "data"
}).error(function () {
// there was an error
});
Now your client-side button click handler can use that, or something like it, to fetch the value from the server. If that's all that button needs to do then don't make it an asp:Button but instead just an input type="button" so that it doesn't post back the whole page. Keeping it as a server-side button would mean canceling the event propagation in JavaScript, which gets ugly with asynchronous operations because there's no immediate way to resume event propagation, you'd have to manually invoke the post back.
I think you can use
Page.ClientScript.RegisterStartupScript
inside your condition if(bvalidate == false) condition like then no need to rely on the value to be set ( i.e in java script function you can remove checking the hidden field value simply alert the user.
Also you can remove this code btnSave.Attributes.Add("onclick", "return fnvalidation()")
Page.ClientScript.RegisterStartupScript(this.GetType(), "validateFnscript", "fnvalidation()",
true);

Telerik Styles with multiple views in ASP.NET MVC

In a previous post I had trouble setting the styles on my views in the same way that they do it on the telerik demo site by selecting the style from a dropdown. This was answered however I now have a new but related problem.
I have multiple pages on my site (as is common to MVC) and each of these pages have many telerik controls on them. Allowing the user to style the site using predefined css done for me is great and saves me a lot of work.
The problem is that when I move from page to page, the combo box that telerik uses resets to its default value, thus resetting the styles on the site everytime the user changes a pages (not ideal).
I have tried using sessions to store the state, but there is no way to detect postback like with standard aspx development. So I cant do something like:
if(isPostBack)
{
if(string.isNullOrEmpty(Session["MyTheme"]+""))
{
Session["MyTheme"]="black";
}
else
{
Session["myTheme"]=//Some combo box selected value
}
}
Even if I could, the combo box onChange event is handled via JavaScript but the Telerik control requires C# Razor and try as I mgiht, I cant get them to talk and share a simple value.
Ultimately all I want to do, is allow the user pick a theme from the combo box and from then on, that theme is remembered throughout the site until they next change it.
I have tried query strings and sessions, but neither work as I cant access them in JavaScript. Aparently they are used on the server side only.
I have tried cookies but that doesnt work because I cant access them in C# Razor. Aparently they are client side only.
Below is my code:
<head>
#(
Html.Telerik().StyleSheetRegistrar()
.DefaultGroup(group => group
.Add("telerik.common.css")
.Add(string.IsNullOrEmpty(#Html.ViewContext.HttpContext.Request.QueryString["theme"]) ? "telerik.black.css" : "telerik."+#Html.ViewContext.HttpContext.Request.QueryString["theme"]+".css").Combined(true).Compress(true)
))
</head>
<body>
#(
/* TELERIK COMBOBOX */
Html.Telerik().ComboBox()
.Name("cbxTheme")
.SelectedIndex(0)
.ClientEvents(events => events.OnChange("cbxTheme_onChange"))
//.BindTo((IEnumerable<DropDownItem>)ViewData["Files"])
.Items(item =>
{
item.Add().Text("black");
item.Add().Text("common");
item.Add().Text("default");
item.Add().Text("forest");
item.Add().Text("hay");
item.Add().Text("metro");
item.Add().Text("office2007");
item.Add().Text("office2010black");
item.Add().Text("office2010blue");
item.Add().Text("office2010silver");
item.Add().Text("outlook");
item.Add().Text("rtl");
item.Add().Text("simple");
item.Add().Text("sitefinity");
item.Add().Text("sunset");
item.Add().Text("telerik");
item.Add().Text("transparent");
item.Add().Text("vista");
item.Add().Text("web20");
item.Add().Text("webblue");
item.Add().Text("windows7");
})
)
#(Html.Telerik().ScriptRegistrar().DefaultGroup(group => group.Combined(true).Compress(true)))
</body>
<script type="text/javascript">
function cbxTheme_onChange()
{
var selectedItemText = $("#cbxTheme").data("tComboBox").text();
//var selectedItemValue = $("#cbxTheme").data("tComboBox").value();
window.location.href = window.location.protocol
+ '//'
+ window.location.host
+ window.location.pathname
+ '?theme='
+ selectedItemText;
}
</script>
As I explained, for the most part it works fine. Execpt when I click on a likn to another page. Then everything gets set back to a preset default.
Ideally what I am looking for is a way to do a postback when a new item is selected in the combo box (like in the JavaScript). The style is changed so the whole page needs to be refreshed anyway. This works. But when I move to another page, it resets to a default style. So I need a way to store the selected style either client side or server side (preferred as my pages are loaded this way).
I have read this can be done by using a controller but it is not clear how. I would like the controller method if possible, because I am going to use a controller to load a list of CSS styles dynamically allowing the user to download additional styles and they will be added to the list automatically. So anything along this line would be great.
You can create a static class with a static property which will act as a global property.
public static class MyTheme
{
public static string MyGlobalTheme { get; set; }
}
or you could you the Application class.
Application["MyTheme"] = "black";
You could put this code in _Layout.cshtml. If your project name is TProj and your static class is in a folder called Objects, it would look like this.
_Layout.cshtml
#{
if (#Html.ViewContext.HttpContext.Request.QueryString["theme"] != null)
{
TProj.Objects.MyTheme.MyGlobalTheme = Html.ViewContext.HttpContext.Request.QueryString["theme"];
}
else
{
if (TProj.Objects.MyTheme.MyGlobalTheme == null)
{
TProj.Objects.MyTheme.MyGlobalTheme = "black";
}
}
}
Now in after this in _Layout.cshtml, you can use the string #TreasuryReportsMvc.Objects.MyTheme.MyGlobalTheme, which should stay the same even when you go to another page. _Layout.cshtml may not be the best place for this logic. You should think about where it makes the most sense for your project.
Be aware that global variables are frowned on by many. This question has a good discussion of Asp.Net MVC global variables.

Using jQuery with ASP.NET to Submit a Form

I've used jQuery dozens of times with PHP with great success. I'm working on an ASP.NET application and would like to use jQuery in the same manner.
Basically, I've got a masterpage that has the form and a webform that has all the form fields and data. A user can submit the form multiple ways - selection of a drop-down, button, etc. I want to catch all submits and use jQuery to submit the form. While the form is being processed, I want to display a new DIV with some text in it. Finally, I want to replace that div with the new form.
How can I accomplish this with the way that ASP.NET works?
Actually ASP.NET will post-back if you use its built-in JavaScript __doPostBack function. There's no other painless way for doing that.
That means you can use jQuery to handle drop-down lists, buttons or whatever (X)HTML element event and handler's body will invoke __doPostBack.
It's unclear that you want is a full-postback, but a partial one using AJAX.
If you're looking for a solution for sending form values to the server without a full-postback, I believe you've these options:
Callback API: http://msdn.microsoft.com/en-us/library/ms178208.aspx
Page methods, update panels: http://msdn.microsoft.com/en-us/magazine/cc163480.aspx
Anyway, let me give you an advise: ASP.NET works quite different compared to PHP and you'd not try to reproduce some known PHP solutions in ASP.NET. You need to change your mind.
About showing a DIV or anything while something is processed, play with initializeRequest ASP.NET AJAX PageRequestManager:
http://msdn.microsoft.com/en-us/library/bb397460.aspx
But that would depend on what AJAX API you're using, because since Microsoft AJAX will be replaced by jQuery in the next times, I'll need to say that you need to do that in some jQuery approach, like creating some $.ajax wrapper so your code will be able to listen when an asynchronous request is going to be made and you can perform actions by handling that situation like showing a DIV or any loading notice.
In ASP.NET Webforms formposts aren't as easy as they are in php. If you're new in ASP.NET development try http://www.asp.net/mvc. A common framework which allows you to implement TypedViews (ViewModes), simple request to modelbinding, and so on...
mh, sample:
[HttpPost]
public JsonResult Insert(string name, string vorname) // name&vorname filled by $_POST:)
{
var #new = new Person { Name = name, Vorname = vorname }
this.repo.Insert(#new);
return this.Json(new { success = true, newId = #new.Id });
}

.NET / jquery - previewing a form result/rendering a view to a string

Here's the situation (using MVC 2.0):
I'm trying to build a feature to allow a user to preview changes they make to their bio/profile without actually committing their changes first. User fills out a form, clicks a "Preview" button and see what their changes look like. One difficulty is the front-end has a different master-page, so we need to render the whole view, not just a control.
Here's the approach I took:
Asynch post the serialized form to a controller action
Manipulate the model to flesh out the collections, etc. that don't get posted
Return the front-end view, passing it this modified model
Catch the response to the asynch method, wrap it in an iframe and write that to a lightboxed div on the page
Code I'm using... Controller action (the BuildPreview method just alters the model slightly)
[HttpPost]
[Authorize]
public ActionResult PreviewProfile(PersonModel model)
{
return View("Person", PeopleService.BuildPreview(model));;
}
HTML/Jquery stuff:
<script type="text/javascript">
$(document).ready(function () {
$("#previewButton").click(function (e) {
$.post("/PreviewProfile", $("#bioForm").serialize(), function (response) {
$("#previewFrame").html(response);
$("#holdMyPreview").modal({
overlayClose: true,
escClose: true,
autoResize: true,
}, "html");
});
});
});
The modal method is just a basic lightbox-esque thing.
Running into two problems:
EDIT - removed this, I was accidentally pulling a child control
The iframe isn't rendering the html (perhaps because it's not valid b/c it's missing html/body/head tags?). If I just drop the response direcltly into the div, without the iframe, it works... albiet with the wrong stylesheet. If I try to insert it into iframe it just treats it as an empty page, just the html, head and body tags show up.
Any thoughts?
Sam
PS: Tried this over at MSDN forums (http://forums.asp.net/t/1675995.aspx/1?Rendering+a+view+into+a+string+) and it didn't get anywhere, figured I'd see if SO has any brilliance.
so, just massage the response when you get it back, add the missing html/body/head
$.post("/PreviewProfile", $("#bioForm").serialize(), function (response) {
response = "<html><body>"+response+"</body></html>";
$("#previewFrame").html(response);
$("#holdMyPreview").modal({
overlayClose: true,
escClose: true,
autoResize: true,
}, "html");
});

Categories

Resources