2

With ASP.NET Webforms, I could drag and drop a control on a form and be able to access its properties:

if (number == 0)
   AddButton.Enabled = false;

Although I cannot drag and drop a control on a ASP.NET MVC View template, can I change its attributes?

For instance:

  • disable a button in some conditions and be able to enable it if conditions change.
  • Be able to change the text of a button from "Next->" to "Finish"
  • etc.
George Stocker
  • 57,289
  • 29
  • 176
  • 237
Richard77
  • 20,343
  • 46
  • 150
  • 252

6 Answers6

4

There are (at least) two Methods to do this:

Method 1: The Simple Way

You would do this by adding logic in your view:

<input type="button" disabled=<%= Model.number <= 0 %> />

Where Model.number is the count of items passed to your view by your controller. If it's less than or equal to zero, disabled will be true.

The syntax may not be exact, I haven't tried this, but this is the path I would go down to do what you want.

This will work for the initial setting of the value; changing it without refreshing the page is a matter of using JavaScript, as other answers have pointed out.

Method 2: The overly complex but more 'MVC' way

If you want the logic in the controller rather than the view, you should set up a specific ViewModel object that you can add the logic to:

ViewModel

public class MyObjectViewModel
{
    MyObject MyObject {get; private set; }
    bool Enabled; {get; set; }
    public MyObjectViewModel(MyObject obj)
    {
        MyObject = obj;
    }
    string IsEnabled
    {
        get
        {
             if (Enabled)
             {
                 return "";
             }
             else return "disabled=disabled";
        }
    }

Controller

public ActionResult Show(int id)
{
    MyObject myObject = repository.GetMyObjectById(id)
    MyObjectViewModel movm = myObject; 
    movm.Enabled = myObject.number > 0;
    return View(movm);
}

View

<input type="button" <%= Model.IsEnabled %> />

Again, the syntax and usage may be a little off, I'm prototyping this off the top of my head, and am not in a location where I can test this for you.

If you're interested in ViewModels, here are some good resources:

I've updated it to return disabled=disabled using the string if it is actually disabled.

Community
  • 1
  • 1
George Stocker
  • 57,289
  • 29
  • 176
  • 237
  • @George Stocker -- This is exactly what I want. I'll try it and get back here as that might also open other doors. – Richard77 Apr 15 '10 at 14:38
  • @George Stocker - I think I would rather see that decision made in the controller than the view. – Mark Apr 15 '10 at 14:45
  • @Mark @Richard77 : See updated answer, I added the logic you'd use if you wanted the controller to make the decision. – George Stocker Apr 15 '10 at 14:59
  • @George: It looks like the 'disable' attribute only recognize one value (). So to make it work, I've used what you wrote as source of the logic. But, I've also wrote an extension method to the HtmlHelper class that I called "InputSubmit". the extension method takes among other a bool parameter that I called "IsEnabled". When IsEnabled = true -> the extension method generates "disabled = disabled". if IsEnabled = false, the extension method generates "" -> the button is disabled – Richard77 Apr 16 '10 at 14:03
  • @Richard77 cool deal, feel free to modify my answer and add the code you used at the bottom so whoever comes along can see what you did. – George Stocker Apr 16 '10 at 14:33
2

All client side behaviour is scripted through javascript. MVC default ships with jQuery for this (www.jquery.com).

I've outlined how you could go about your examples:

<input id="nextFinishBtn" type="button" value="Next ->"/>

Assume you want to change this to "Finish" if the user unchecks a checkbox named "Configure Advanced settings". which was true by default

<%= Html.CheckBox("DoAdvancedSettings", "true", new { onclick='changeNextButton()' }); %>
<script langauge="javascript">
    function changeNextButton() {
        $('#nextFinishBtn').val('Finish');
    }
</script>

In general you can access any attribute of any element in jQuery using the .attr construct:

$('#nextFinishBtn').attr('disabled','disabled');

You call it with two parameters to set a value, and with just one to fetch the value. So to see if the button is disabled, you'd do:

if ($('#nextFinishBtn').attr('disabled')=='disabled') { alert('button is disabled'); }
Soraz
  • 6,610
  • 4
  • 31
  • 48
0

ASP.NET MVC is a lightweight programming model. It does not create a control object model for you at the server the way plain ASP.NET does. Typically, you would use client-side javascript (possibly with help from JQuery) to manipulate the properties of controls that are put on the page by the markup in your view.

If you want to get a quick start with ASP.NET MVC, check out Sharp Architecture (open source). They have guidance and all sorts of goodies to help you get productive with ASP.NET MVC quickly.

Tom Cabanski
  • 7,828
  • 2
  • 22
  • 25
  • How about if I want to modify the attributes before the HTML is generated. Let's imagine something simple. I've a collection that I display. I've also a button whose text is "Remove". I don't know in advance the size of the collection. If the collection is 0, should I keep the Remove button enabled when the view renders? I'm not saying that I want to change the text of the button after the view has rendered, but before it renders – Richard77 Apr 15 '10 at 13:32
  • @Richard77 I make _all_ decisions like that in your controller and keep the view as dumb as possible. I would have a property on my model for `ShowRemoveButton` and the view would look at that to show or hide the remove button. – Mark Apr 15 '10 at 14:43
  • @Mark -- Can you give a sample to illustrate this (without using Javascript -- just as Goerge Stocker pointed out)? – Richard77 Apr 15 '10 at 15:01
  • @Richard77 - It is unclear if you want this to happen on the server or on the client. George's answer is spot on if you need it to happen on the server, and I would. If want it to happen on the client, jQuery, as Tom said, is your easiest bet. – Mark Apr 15 '10 at 15:18
  • @Mark -- I've heard all the preachings everywhere on how programmers need to set essential functionalities without touching to Javascript. That said, I agreed with @George. However, when you said it's better to put the logic in the controller, I was waiting for you to do it (I think that's what you did when you edited you answer). – Richard77 Apr 15 '10 at 15:26
  • @Richard77 - From your question it wasn't clear if you wanted to do it in the controller, JavaScript or the view itself. I definitely wouldn't make that _decision_ in the view, which is what it sounded like you wanted to do in the initial reply to Tom..."modify the attributes before the HTML is generated". You need to generate the text box there, but decide if it is enabled in the controller. My answer simply showed using a `HtmlHelper ` extension to build the text box and how you could pass in the disabled attribute. By the time I saw your comment, George already had a perfect example. – Mark Apr 15 '10 at 16:20
  • @Mark-- Anyway, thanks a lot to all of you. As I said earlier, your answer open a big door to many subject I need to explore in the coming days. – Richard77 Apr 15 '10 at 20:40
0

Generally, you rarely want to do this. The MVC way is:

  1. Let your controller populate the model with the objects needed to generate the HTML
  2. Pass the model to the appropriate view
  3. Let the view output the HTML based on the values of the objects in the model.

If you often find yourself in need of modifying HTML attributes after the HTML has been generated, you're probably not applying this pattern correctly.

Jonas Høgh
  • 10,358
  • 1
  • 26
  • 46
  • How about if I want to modify the attributes before the HTML is generated. Let's imagine something simple. I've a collection that I display. I've also a button whose text is "Remove". I don't know in advance the size of the collection. If the collection is 0, should I keep the Remove button enabled when the view renders? I'm not saying that I want to change the text of the button after the view has rendered, but before it renders. – Richard77 Apr 15 '10 at 13:29
0

I would check out the HTML helpers.

<%= Html.Button("AddButton","Button Text",HtmlButtonType.Submit,"SomeJavaScriptFunction()",new {disabled="disabled"} )  %>

The only real gotcha is the anonymous class at the end gets funny when you add attributes that are keywords. For example, to add a Css class you need an anonymous class that looks like this new {@class="myCssClassName"}.

Mark
  • 9,966
  • 7
  • 37
  • 39
0

As I replied to George Stocker, I've noticed that the disabled attribute can get only 1 value (disabled = "disabled"). Also, anything else disable the input control as well. For instance, disabled = true and disable = false will still disable the control.

It looks like (I'm not sure) having disabled attribute disables the control and not having it enables the control. So I decided to write a extension method to the HtmlHelper class.

public static class MyHelperClass
{
  public static string InputDisable(this HtmlHelper html, string name, string myValue,     bool isEnabled)
  {
    string show = "";
    if(!isEnable)
       show = "disabled = \"disabled\"";
    return "<input type = \"submit\" value = \"" + myValue + "\"" + show + " />";
  }
}

Now I can access the method this way

<% = Html.InputDisable("myInput", "My Button", false)%>

So the last param determines weather the input control is visible.

Now using the Goerge Stocker logical, I can define the value of isEnabled .

Thanks for all your answers

Richard77
  • 20,343
  • 46
  • 150
  • 252