DmitryEfimenko / TwitterBootstrapMvc

Fluent implementation of ASP.NET-MVC HTML helpers for Twitter Bootstrap.
Apache License 2.0
224 stars 79 forks source link

width attributes? #140

Closed fdsanto closed 10 years ago

fdsanto commented 10 years ago

hi ! this is kind of a basic question but i can't change the controls width, i've tried using WitdhSm/Md/Lg with different int values but it doesn't make any changes, i'm i missing something? also inputSize just changes the inputs height and font but not the width :( should i just use some css class?

thx!

Franco

DmitryEfimenko commented 10 years ago

InputSize helper is there to accommodate this bootstra's functionality. So that works appropriately.

As to Width change... it all works for me. Show me some code and I'll try to point out the issue.

fdsanto commented 10 years ago

well, for example if i use @f.FormGroup().TextBoxFor(model => model.Venta.Cliente.Nombre).WidthSm(10) nothing happens

DmitryEfimenko commented 10 years ago

I probably should document this stuff a bit better (or maybe I should change functionality a bit).

Right now Width will only be applied to controls under Form of type Horizontal or Inline. Make sure you specify which one you are using.

If that still does not work for you, please show me more code!

fdsanto commented 10 years ago

Ok, i see how to set the width on different inputs inside a form, but apparently it doesn't work so great on several appended inputs

here, i've a disabled textbox indicating a default client's name, and appended to it two more textbox with typeahead for searching and changing the client's name according to those two parameters.. well the problem is that the appended textboxes' width are too small and i've tried changing them with WidthMd(3) but the styles get broken.. i know it's kind of complex, maybe i should separate each textbox but it was looking great in a single control..

@using (var f = Html.Bootstrap().Begin(new Form().Type(FormType.Horizontal).WidthMd(3))) {
@(f.FormGroup().TextBoxFor(model => model.Venta.Cliente.Nombre) .Disabled() .Append( f.FormGroup().TextBox(" ").WidthMd(3) .TypeAhead(new TypeAhead() .Controller("Cliente") .Action("CheckClienteByDNI") .Updater("changeClienteByDNI") ).WidthMd(5).Append(Html.Bootstrap().Label("DNI")) .Append( f.FormGroup().TextBox(" ").WidthMd(3) .TypeAhead(new TypeAhead() .Controller("Cliente") .Action("CheckClienteByCUIT") .Updater("changeClienteByCUIT") ).Append(Html.Bootstrap().Label("CUIT")) .Append(Html.Bootstrap().Button().Text("Nuevo") .TriggerModal("clienteModal") ) ) ) )

DmitryEfimenko commented 10 years ago

First of all, when you use FormGroup() it will render not only textbox (or other input), but also label for it. So you do not need to have separate label helper appended. Second, I don't think you are using .Append method as intended. I think what you actually want is to use a .CustomControls method. Though I might be mistaken. It would be easier to tell if you showed me what kind of html output you are looking for.

fdsanto commented 10 years ago

image

I wanted exactly that but with more space for DNI/CUIT textboxes, it's no problem i can take the appended inputs and place them above the main textbox

DmitryEfimenko commented 10 years ago

I kind of have an alternative:

@using (var f = Html.Bootstrap().Begin(new Form().Type(FormType.Horizontal)))
{
    @(f.FormGroup().TextBoxFor(model => model.Venta.Cliente.Nombre).Disabled()
        .Append(Html.Bootstrap().TextBox("DNI").Placeholder("DNI").Typeahead(...))
        .Append(Html.Bootstrap().TextBox("CUIT").Placeholder("CUIT").Typeahead(...))
        .Append(Html.Bootstrap().Button().Text("Nuevo").TriggerModal("clienteModal")))
}

As you can see you would not need labels since there are placeholders in the inputs. There is just one issue with this. BMVC does not handle appending inputs quite right. I just noticed it. it wraps inputs into span with class input-group-addon when it should wrap it in the span with class input-group-btn. There still would be a need to adjust width of these inputs using css, but that will look cleaner. I'll fix this issue. Let me know if that approach will work for you.

fdsanto commented 10 years ago

it didn't quite fix it, but don't worry maybe i was over-complicating things.. one more thing, i'm trying to place both typeahead txtbox and button above the main txtbox(Nombre), is it possible to place controls in a inline manner inside a horizontal form? (without appending things =P)

thanks for all the help!

EDIT: disregard this, got it working on a horizontal form and it looks great by just placing one input after another. thx!

DmitryEfimenko commented 10 years ago

I'll give you an idea how this could be done below, but probably some css adjustments will have to be done too:

@using (var f = Html.Bootstrap().Begin(new Form().Type(FormType.Horizontal)))
{
    @(f.FormGroup().CustomControls(
        MvcHtmlString.Create("<div class='form-inline'>"),
        @f.FormGroup().TextBoxFor(x => x.CoolName).Disabled().Label().Class("sr-only"),
        @f.FormGroup().TextBox("DNI").Label(),
        @f.FormGroup().TextBox("CUIT").Label(),
        Html.Bootstrap().Button().Text("Nuevo").TriggerModal("clienteModal"),
        MvcHtmlString.Create("</div>")
    ).LabelFor(x => x.CoolName))
}
fdsanto commented 10 years ago

thanks Dmitry! i'll give it a try as soon as i can

2013/10/30 Dmitry A. Efimenko notifications@github.com

I'll give you an idea how this could be done below, but probably some css adjustments will have to be done too:

@using (var f = Html.Bootstrap().Begin(new Form().Type(FormType. Horizontal))) { @(f.FormGroup().CustomControls( MvcHtmlString.Create("

"), @f.FormGroup().TextBoxFor(x => x.CoolName).Disabled().Label().Class("sr-only"), @f.FormGroup().TextBox("DNI").Label(), @f.FormGroup().TextBox("CUIT").Label(), Html.Bootstrap().Button().Text("Nuevo").TriggerModal("clienteModal"), MvcHtmlString.Create("
") ).LabelFor(x => x.CoolName)) }

— Reply to this email directly or view it on GitHubhttps://github.com/DmitryEfimenko/TwitterBootstrapMvc/issues/140#issuecomment-27411900 .

DmitryEfimenko commented 10 years ago

also, this could be of help

sgentile commented 10 years ago

I'm having the same issue. Your examples help.

How would you do something like this : http://jsfiddle.net/tdUtX/2/

DmitryEfimenko commented 10 years ago

well, this one looks to me like a simple Form with just modified input widths:

@using (var f = Html.Bootstrap().Begin(new Form()))
{
    @f.FormGroup().TextBoxFor(x => x.ShortField).WidthXs(6)
    @f.FormGroup().TextBoxFor(x => x.ShortField).WidthXs(6)
    @f.FormGroup().TextBoxFor(x => x.FullWidth)
}

Let me know if I misunderstood something.

sgentile commented 10 years ago

This doesn't work as you need inline or horizontal ? But I'm not wanting either - I want a basic form with the input boxes smaller ?

DmitryEfimenko commented 10 years ago

If it does not work like that, it's a bug. I'll take a look at it in the evening.

sgentile commented 10 years ago

ok thanks!

DmitryEfimenko commented 10 years ago

So I see the problem now. I guess the real purpose here is to be able to render multiple inputs in a row like in this fiddle.

Even if I made sure that BMVC renders inputs like in your example - surrounds it with <div class="col-xs-6"> and puts class row on the <div class="form-group">, it would not take care of the root issue because there still would be no way to put multiple inputs in the form group.

So we just need to think of an intuitive BMVC syntax that would allow for this functionality. Here is one possibility:

@using (var f = Html.Bootstrap().Begin(new Form()))
{
    using(f.FormGroup().BeginRow())
    {
        @f.TextBoxFor(x => x.Address).WidthXs(6).Label()
        @f.TextBoxFor(x => x.City).WidthXs(3).Label()
        @f.DropDownListFor(x => x.State).WidthXs(3).Label()
    }
    @f.FormGroup().Row().TextBoxFor(x => x.ShortField).WidthXs(6) // shortcut
    @f.FormGroup().TextBoxFor(x => x.FullWidth) // full widht, so .Row() does not need to be applied
}

For convenience there would also be a short cut .Row() for a single input that needs to be in a row.

Let me know what you think.

sgentile commented 10 years ago

That looks good to me - solves the root issue as well as allows some flexibility on the row layout for multiple inputs

DmitryEfimenko commented 10 years ago

As I was going through possible use cases with this, I saw that this would really only work for textboxes and dropdowns because they look alike, If you try to put checkbox, radiobutton, listbox, or of course textarea, the layout becomes screwed up. Your scenario is kind of unique and building helper methods for it like proposed above will introduce confusion. I can already imagine questions asked about this every day. So I propose a different solution, that will be more generic and maybe will cover more situations because I now think it all really comes down to a question "how do I wrap my inputs in the <div class="col-xs-6">?": Introducing helper .Col():

@using (var f = Html.Bootstrap().Begin(new Form()))
{
    @(f.FormGroup().Class("row").CustomControls(
        f.Col(f.TextBoxFor(x => x.Address).Label()).Xs(6),
        f.Col(f.TextBoxFor(x => x.City).Label()).Xs(3),
        f.Col(f.DropDownListFor(x => x.State).Label()).Xs(3)
    ))
}

So we have here FormGroup().Class() method. That functionality already exists. It just provides a way to slap any class on <div class="form-group"> We have .CustomControls((..). This helper exists as well. It allows to put multiple controls in the form group. The helper .Col() will take any IHtmlString and essentially wrap it in <div class="col-*-*"> I think with such approach it will be more transparent what is going on and why html is rendered the way it is.

Let me know what you think.

sgentile commented 10 years ago

"I think with such approach it will be more transparent what is going on and why html is rendered the way it is."

I agree - looks good! thanks

DmitryEfimenko commented 10 years ago

This is done. Changed Col to be Div for even more clarity. This element also has .VisibleDependsOn() method. the following syntax is now possible:

@using (var f = Html.Bootstrap().Begin(new Form()))
{
    @(f.FormGroup().CustomControls(
        Html.Bootstrap().Div(Html.Bootstrap().TextBox("Address").Label()).Xs(6),
        Html.Bootstrap().Div(Html.Bootstrap().TextBox("State").Label()).Xs(3),
        Html.Bootstrap().Div(Html.Bootstrap().TextBox("Zip").Label()).Xs(3)
    ))
}
sgentile commented 10 years ago

thank you - fantastic!

sgentile commented 10 years ago

I¹m still having an issue with this ­ can I email you on it ?

From: "Dmitry A. Efimenko" notifications@github.com Reply-To: DmitryEfimenko/TwitterBootstrapMvc <reply+i-21778925-fb1e9204704439aafd6fd08d4265c68efafccce7-132404@reply.gith ub.com> Date: Friday, December 13, 2013 at 5:03 AM To: DmitryEfimenko/TwitterBootstrapMvc TwitterBootstrapMvc@noreply.github.com Cc: Steve Gentile steven.gentile@gmail.com Subject: Re: [TwitterBootstrapMvc] width attributes? (#140)

Closed #140 https://github.com/DmitryEfimenko/TwitterBootstrapMvc/issues/140 .

‹ Reply to this email directly or view it on GitHub https://github.com/DmitryEfimenko/TwitterBootstrapMvc/issues/140 .

sgentile commented 10 years ago

Some problems here: When I use your example above, it puts the controls inline, even though the form is horizontal.*

Also when I use this: @(f.FormGroup().CustomControls( Html.Bootstrap().Div(Html.Bootstrap().DropDownListFor(model => model.General.Sample, new SelectList(Model.Samples, "Id", "Name")).Label()).Xs(4) ))

The width does get set now, however the entire FormGroup is indented.

*also to prevent inline, this means I have to put that entire section each time for every control on the form. ie.

@(f.FormGroup().CustomControls( Html.Bootstrap().Div(Html.Bootstrap().DropDownListFor(model => model.General.Sample, new SelectList(Model.Samples, "Id", "Name")).Label()).Xs(4) )) @(f.FormGroup().CustomControls( Html.Bootstrap().Div(Html.Bootstrap().DropDownListFor(model => model.General.Sample, new SelectList(Model.Samples, "Id", "Name")).Label()).Xs(4) )) @(f.FormGroup().CustomControls( Html.Bootstrap().Div(Html.Bootstrap().DropDownListFor(model => model.General.Sample, new SelectList(Model.Samples, "Id", "Name")).Label()).Xs(4) ))

sgentile commented 10 years ago

All that is needed with a horizontal form to control the input size is the ability to change the class on the div

ie. @f.FormGroup().DropDownListFor(model => model.General.Ex, new SelectList(Model.Exs, "ExId", "ExName"))

This produces:

div class=" form-group"
label class="control-label col-lg-2" ...
div class="col-lg-10
    //input here...
div
div

All I need to be able to do is change that div width that wraps the input.

ie. if I'm in chrome and make that

it works perfectly.

I have yet to find the solution that does this

DmitryEfimenko commented 10 years ago

Looking back at this post - we were talking about a regular form - not horizontal. I was building a way to support example in this fiddle. I'll take a look what happens when form in horizontal this evening.

As for your last comment, you should be able to change width of that div with something like:

@f.FormGroup().DropDownListFor(model => model.General.Ex, new SelectList(Model.Exs, "ExId", "ExName")).WidthSm(4)

Let me know if this is not the case for you or if I misunderstand the issue.

sgentile commented 10 years ago

I call it horizontal because of the label location. In that example, the labels are above the inputs, and the input widths are controlled by setting the class on the wrapping it. I will give that a try and report back

sgentile commented 10 years ago

An example

<div class="form-group row">
    <div class="col-xs-6">
        @Html.LabelFor(model => model.General.IncidentTypeId)
        @Html.DropDownListFor(model => model.General.IncidentTypeId, new SelectList(Model.IncidentTypes, "IncidentTypeId", "Name"), new {@class="form-control"})
        @Html.ValidationMessageFor(model => model.General.IncidentSubmissionDate)
    </div>
</div>

That formats exactly how I need it to. It's left justified, and it the exact width.

I keep trying different options with what you provided, it's not formatting at all how this does above.

DmitryEfimenko commented 10 years ago

I'm not testing this right now. Will be able to take a closer look in the evening, but from the looks of it I just forgot to put class "row" on the FormGroup and render validation message. The below should do it.

@using (var f = Html.Bootstrap().Begin(new Form()))
{
    @(f.FormGroup().Class("row").CustomControls(
        Html.Bootstrap().Div(Html.Bootstrap().TextBox("Address").ShowValidationMessage(true).Label()).Xs(6),
    ))
}
sgentile commented 10 years ago

that solved the issue - let me know when you commit with that included (or if you plan on it) and I will update to latest!

DmitryEfimenko commented 10 years ago

this should be already released. Please get latest and make sure it works as expected.

sgentile commented 10 years ago

I have TwitterBootstrapMVC - MVC4 3.9.0 and it requires Class("row") on it to get the result as I posted above

sgentile commented 10 years ago

Here is an example of what I have to do :

@(f.FormGroup().Class("row").CustomControls(Html.Bootstrap().Div(Html.Bootstrap().TextBoxFor(model => model.Person.SubscriberNumber).Label()).Xs(6)))
DmitryEfimenko commented 10 years ago

that looks like exactly what I've posted in my previous comment. Does that work all right for you?

sgentile commented 10 years ago

works well, I had misunderstood when you said you forgot to put 'row' on the item - thanks!