MVC: get uploaded filename back in grid column

2019-08-14 15:35发布

问题:

I have an MVC razor form with a Kendo grid. The grid has an asynch image uploader.

@(Html.Kendo().Grid<CraftStore.Models.Catalog>()
.Name("CatalogGrid")
.Columns(columns =>
{
    columns.Bound(p => p.CatalogName).Filterable(true).Width(240);
    columns.Bound(p => p.CatalogDescription).Filterable(true).Width(340);
    columns.Bound(p => p.ModelNumber).Filterable(true).Width(110);
    columns.Bound(p => p.SerialNumber).Filterable(true).Width(110);
    columns.Bound(p => p.InventoryCount).Filterable(true).Width(110);
    columns.Bound(p => p.WebPrice).Title("Price").Format("{0:C}").EditorTemplateName("Currency").Width(110);
    columns.Bound(p => p.ImagePath).ClientTemplate("<img height='80' src='" + Url.Content("~/Content/Images/catalog/Products/") + "#=data.ImagePath#' title='#=data.ImagePath#' alt='#=data.CatalogName#' />").EditorTemplateName("Image").Title("Picture").Width(300);
    columns.Command(command => command.Destroy()).Width(110);
})
.ToolBar(toolbar =>
{
    toolbar.Create();
    toolbar.Save();
})
.Editable(editable => editable.Mode(GridEditMode.InCell))
.Filterable(filterable => filterable
    .Extra(false)
    .Operators(operators => operators
        .ForString(str => str.Clear()
            .Contains("Contains")
            .StartsWith("Starts with")
            .IsEqualTo("Is equal to")
            .IsNotEqualTo("Is not equal to"))
        .ForNumber(num => num.Clear()
            .IsEqualTo("Is equal to")
            .IsNotEqualTo("Is not equal to")
            .IsGreaterThan("Greater than")
            .IsLessThan("Greater than"))
    ))
.Navigatable()
.Selectable(selectable => selectable.Type(GridSelectionType.Row))
.Scrollable(scrollable => 
{
        scrollable.Virtual(true);
        scrollable.Height(400);
})
.Events(events =>
{
    events.Change("change");
})
.DataSource(dataSource => dataSource
    .Ajax()
    .Batch(true)
    .PageSize(20)
    .Model(model =>
        {
            model.Id(p => p.Id);

        }
        )
    .Events(events =>
    {
        events.Error("error_handler");
    })
    .Create("CatalogEditing_Create", "WebCatalog")
    .Read("CatalogEditing_Read", "WebCatalog")
    .Update("CatalogEditing_Update", "WebCatalog")
    .Destroy("CatalogEditing_Destroy", "WebCatalog")
)
)

All work fine! - the image has a tooltip of the filename... The upload and remove work great...

I have an edit template for image (image.cshtml in Views/Shared/EditorTemplates)

The template is:

@model string 

<div style="width:100%">
    <div class="section">
        @Html.TextBoxFor(model => model, new {@class="k-textbox result-box" })
         @(Html.Kendo().Upload()
          .Name("files")
          .Events(events=>events.Success("OnUploadSuccess"))
          .Multiple(false)
          .Async(a => a
             .Save("Save", "Upload")
             .Remove("Remove", "Upload")
             .AutoUpload(true)
          )
      )
    </div>
</div>

The OnUploadSuccess js function (which is defined on the razor view) has the success function

<script type="text/javascript">
    //file upload scripts
    function getFileInfo(e) {
        return $.map(e.files, function (file) {
            var info = file.name;

            // File size is not available in all browsers
            if (file.size > 0) {
                 info += " (" + Math.ceil(file.size / 1024) + " KB)";
            }
            return info;
         }).join(", ");
     }

     function OnUploadSuccess(e) {
            $(".result-box").value = getFileInfo(e);
            Model = getFileInfo(e);
     }

all works fine - the variable 'Model' does get the correct filename.

Now...

How do I get that filename value returned by getFileInfo(e) to be the current value for the grid column???

I thought 'Model' would work, but it does not.

Model = getFileInfo(e); 
//since this is in a template, I thought it would bind 'Model' to the column 

Then, you can see above, in OnUploadSuccess, I also thought it could be done by using jQuery :

$(".result-box").value = getFileInfo(e);

The jQuery does find and set the value, but the row's member named ImagePath never gets the resulting value.

Neither work, and I'm not sure how to get the returned filename to be the column value.

Any help appreciated.

UPDATE:

Well, I've updated the OnUpdateSuccess js function:

var fn = getFileName(e);
$("#ImagePath").val(fn)

And this now updates the field - but this is not saving when you tab out of the field or immediately hit save. In either care, the old value is restored.

How do I get it to stay? I imagine this is where the MVVM binding will help?

回答1:

After working with the amazing support from Telerik, I was right - it's a binding issue because the MVVM doesn't know about my change. To get it to know about my change I need to add a line after the script change above:

       $("#ImagePath").trigger("change");

Now, it works perfectly!