I am making an if check in the controller
if(validDate<DateTime.Now)
{
//TODO
}
And what I want to do is to hide a specific button in my view if this statement is true, otherwise show it. I am also using jquery in front end.
Can someone help me to manipulate the html element, the button, from the controller, example add a style class or something?
In this case I need to make the changes from the controller and not from the jquery, but I can use the jquery after if needed.
You need to use models (aka as ViewModel), #thomashaid already gave you a comment with a useful article: Views And ViewModels.
Create a class in the "Models" folder of your MVC Project. Like this:
public class MyViewModel
{
public bool ShowButton { get; set; }
}
Then in your controller, create an object of your ViewModel class and assign the corresponding value to the ShowButton property. Then pass the ViewModel to the returning view:
public ActionResult MyAction()
{
var myViewmodel = new MyViewModel();ยด
if(validDate < DateTime.Now)
{
myViewModel.ShowButton = true;
}
return View(myViewModel);
}
Finally, use razor syntax in your view to manipulate the HTML code that will be returned to the client:
#model MyViewModel
#if (Model.ShowButton)
{
<Button>now you see me</Button>
}
Related
I'm working on an MVC Web application with ASP.NET and Knockout js (V3.5.1).
I'm struggling with Knockout observable not updated when an input value is change. Both of them are dynamically created in Javascript. The initial value set to the observable is not reflected on the input when the observable is created. I'm puzzled why the observable not catching the input's change.
Please find my code below for further demonstration. I really appreciate if there is any help.
CustomViewModel.cs
public class CustomViewModel
{
public int Id { get; set; }
public int Prop { get; set; }
}
HTML with Razor
#model CustomViewModel
<div id="inputContainer"></div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval", "/Scripts/ViewModels/CustomFormViewModel.js")
<script>
var vm = new CustomFormViewModel(#HtmlHelperExtensions.HtmlConvertToJson(Html, Model));
vm.createInput = function (data) {
return `#Html.Editor("Prop", new { #htmlAttributes = new { #id = "${data.Id}Prop", #data_bind = "value: ${data.Id}Prop" } })`;
};
ko.applyBindings(vm);
</script>
}
/Scripts/ViewModels/CustomFormViewModel.js code
function CustomFormViewModel(self) {
var self = this;
var data = loadData();
self[`${data.Id}Prop`] = ko.observable(data.Prop);
var newInput = self.createInput(data);
$("#inputContainer").append(newInput);
};
I will only focus on the issue at hand- which is the input.
In general, since you are using knockoutJS you should refrain from using jQuery to append elements to the dom, instead you should change your View, so that it reflects what you are trying to achieve.
So you should have something like so:
<div data-bind="if: showThisInput">
<input data-bind="value: myBindedObservable"
</div>
This way you control if the input should be rendered/shown, instead of appending it later on via jQuery.
When you call applyBindings you only bound to any html already existing on the view. Because you are injecting the input AFTER you have already bound the vm to the view, the engine does not know of the element since its not controlled by knockout, but rather added by you manually.
One way to solve this would be to actually call the razor inside the normally rendered view, so that when the applyBindings is executed, the input element exists on the dom
#Html.Editor("Prop", new { #htmlAttributes = new { #id = "${data.Id}Prop", #data_bind = "value: ${data.Id}Prop" } })
The only other option would be to clearBindings on the element and-rebind, which is also a bad practice for this use-case.
c# code:
public class Person{
public string Name { get; set; }
public age int { get; set; }
}
cshtml code which generates an id of #Person_Name
#Html.DropDownListFor(m => m.Person.Name)
javascript code:
$('#Person_Name').on("change", function () {
//Do something
}
If I change the Person class property name from Name to FullName. The next step is to modify the cshtml code to read as:
#Html.DropDownListFor(m => m.Person.FullName)
I understand you can manually go in and change the Jquery code, but if this change is made and the person making the change is unaware of the jquery, it is going to cause an error. Is there a way to prevent this from happening through some form of notification or logging? Rather than just remembering that the jquery needs to be changed.
You do have the option to use:
#Html.IdFor(x => x.Person.FullName)
Or
#Html.NameFor(x => x.Person.FullName)
That does rely on having small bits of script in pages, but for what id do this is mostly calling functions in .js resources which from my point of view I find better for reuse anyway.
You may still not get alerted to all issues unless you choose to compile your MVC views, you'll probably get a warning if you have the view open. How you set up your project to compile your MVC views will depend on the type of project but a quick Google should help with that one.
I am making a web app which make use of multiple tabs.
I want show a Data of one type in one tab e.g Student Profile in one tab
And in other Tab a different model is needed e.g i need the Registeration model class in the same view
Yes you can by using either System.Tuple class (or) by means of using a ViewModel (a custom class)
ViewModel Option
public class ViewModel1
{
public StudentProfile profile {get; set;}
public Registration Reg {get; set;}
}
Pass this ViewModel1 as your model object to the view (or) bind your view with this model object. It's better than using a Tuple<T1, T2>
Yes, you could just add a main view model then nest the tab models within the main view model
public class YourMainViewModel
{
public Tab1ViewModel Tab1 {get; set;}
public Tab2ViewModel Tab2 {get; set;}
}
Then in your view, just pass the tab models to your partials (if you are using partials for your tabs)
#{Html.RenderPartial("Tab1", Model.Tab1);}
#{Html.RenderPartial("Tab2", Model.Tab2);}
Yes, I know at least 3 ways to set some models in a single view, but i think the best practice it's to use ViewModels.
If you are using entity framework you can do something like that.
Set in Models a class which will be you ViewModel.
public class StudensP_Registration
{
public IEnumerable<StudentsProfile> studentsp { get; set; }
public IEnumerable<Registration> registration { get; set; }
}
Then you call it in your controller like this.
public ActionResult Index()
{
StudensP_Registration oc = new StudensP_Registration();
oc.studentsp = db.StudentsProfile;
oc.registration = db.Registration;
return View(oc);
}
And then in the view
#using Proyect_name_space.Models;
#model StudensP_Registration
#foreach (ordenes_compra item in Model.studentsp) {#something you want..}
I hope i can help you.
I am using .NET MVC4 and have created a number of PartialViews that are all used as templates. I use Backbone.js and Backbone.Marionette.js for my client-side code and have created the templates used in my Backbone Views as RAZOR PartialViews.
I created a Controller called TemplatesController that has a ChildAction and given a name of PartialView it returns the MvcHtmlString for that PartialView which is my template. I can then use the template along with Handlebars to create my View in Backbone.Marionette.
This all works great for me but I have to call the Controller action for every PartialView that exists. My list of templates is growing and I would like to not have to add a new call render the template every time to my Index View.
My question is, is there a better way to just call the Controller once and return all PartialViews that exist? Thanks for any suggestions.
Here is my Controller method
[ChildActionOnly]
public ActionResult GetTemplate(string name) {
return PartialView(name);
}
Here is a HtmlHelper Method I use to call the Controller Action
public static MvcHtmlString Template(this HtmlHelper htmlHelper, string name) {
// call ChildAction on our controller to get the HTML for this template
return htmlHelper.Action("GetTemplate", "Templates", new { name = name });
}
Here is example of how I load templates into Index or _Layout view using Helper. For each PartialView I create I add a line but I would like to remove these and do it in one line such as Html.AllTemplates or something.
#Html.Template("SiteHeader")
#Html.Template("SiteFooter")
I stripped all the content out but this would be example of what would be in each of the partial views, the main thing to note is it is wrapped inside a script tag
<script id="site-header" type="text/x-handlebars-template">
<h3>{{headertext}}</h3>
<div>{{somevalue}}</div>
</script>
I have a view that displays several checkbox lists of items in tables (the lists are dynamic). I need to know how to update the ViewModel when the user clicks on a checkbox so that when control returns to the controller it can inspect the viewmodel to determine which items were selected.
The VM contains several properties such as
public IEnumerable<IFilterItem> Cities;
public Interface IFilterItem
{
int ID { get; set; }
string Name { get; set; }
bool IsSelected { get; set; }
}
What I need help with is how to set the view's copy of the model data in the checkbox's onclick handler. Thanks as always, you guys are great!
Are you using the CheckBoxFor helper? If so, when control returns to the controller your view model should just have IsSelected set based on the state of the checkbox.