ForeignKey column not working in PopUp edit mode: doesn't show the correct item selected

4 posts, 1 answers
  1. Stargazer
    Stargazer avatar
    2 posts
    Member since:
    Sep 2008

    Posted 26 Jul 2013 Link to this post

    Hello! :)

    I've searched for all over the place (understatement) for a solution to my case to no avail until now. First, I'll explain my scenario:
    - I have an OpenAccess Model exposed as a WCF Data Service (oData v3);
    - I have an Kendo MVC Application;
    - I have a View with a grid, set for PopUp editing, AJAX Bound;
    Before posting some code, let me explain my issue/difficulty. I have an entity with these properties:
     - TextoID
     - Titulo;
     - Corpo;
     - TipoTextoID;
     - TipoTexto;

    There is a ForeignKey column set to the TipoTextoID property which get's correctly populated either in in-line or pop-up mode. But when it comes to changing data, it only works in-line mode. This is my issue I need it to work in a popup, since the "Corpo" property is bound to a KendoUI Editor.
    When in the popup, it does not show the correct value on the dropdown. It shows always the first item on the dropdown.
    Honestly I'm feeling stupid. I tried almost every sample, post, article I could find to no avail and I'm clueless.
    I hope someone can help me on this. Thanks in advance to all!

    So, here's the code.
    The view:
    01.@model IEnumerable<KendoMVC.CostSimulatorService.Texto>
    02. 
    03.@{
    04.    ViewBag.Title = "Textos";
    05.    Layout = "~/Views/Shared/_Layout.cshtml";
    06.}
    07. 
    08.<h2>Textos</h2>
    09. 
    10.@(Html.Kendo().Grid(Model) // Bind the grid to the Model property of the view
    11.      .Name("Grid")
    12.      .Columns(columns =>
    13.      {
    14.          columns.Bound(p => p.Titulo);   //Create a column bound to the "ProductID" property
    15.          columns.Bound(p => p.IsPrivado)
    16.              .ClientTemplate("<input type='checkbox' #= IsPrivado ? checked='checked': '' # class='chkbx' />")
    17.              .Width(170); //Create a column bound to the "ProductName" property
    18.          columns.ForeignKey(p => p.TipoTextoID,
    19.                                 (System.Collections.IEnumerable)ViewData["TiposTexto"],
    20.                                 "TipoTextoID",
    21.                                 "Designacao")
    22.                            .Title("Tipo de conteúdo").Width(170);
    23.          columns.Command(command =>
    24.          {
    25.              command.Edit();
    26.              command.Destroy().Text("Remover");
    27.          }).Width(200).Title("Acções");
    28.      })
    29.      .ToolBar(commands => commands.Create())
    30.          .Editable(editable => editable.Mode(GridEditMode.PopUp)
    31.              .TemplateName("Texto")
    32.              .Window(builder => builder
    33.                  .Width(800)
    34.                  .Height(570)
    35.                  .Modal(true)
    36.                  .Resizable(c => c.Enabled(true))
    37.                  .Animation(true)
    38.                  .Title("Editar conteúdo")))
    39.      .DataSource(dataSource => dataSource
    40.            .Ajax() //specify server type
    41.            .PageSize(20)
    42.            .Events(events => events.Error("error_handler"))
    43.            .Model(model =>
    44.            {
    45.                model.Id(texto => texto.TextoID); // Specify the property which is the unique identifier of the model
    46.                model.Field(texto => texto.TextoID).Editable(false); // Make the ProductID property not editable
    47.            })
    48.            .Create(create => create.Action("CreateTexto", "Textos"))
    49.            .Read(read => read.Action("ReadTextos", "Textos"))
    50.            .Update(update => update.Action("UpdateTexto", "Textos"))
    51.            .Destroy(destroy => destroy.Action("DestroyTexto", "Textos")))
    52.     .Pageable() // Enable paging
    53.     .Sortable() // Enable sorting
    54.     .Selectable()
    55.     .Filterable()
    56.     .Scrollable()
    57.         )
    58. 
    59.<script type="text/javascript">
    60. 
    61.    $(document).ready(function() {       
    62.        $("form.k-edit-form").kendoValidator();
    63.    });
    64. 
    65.    function error_handler(e) {
    66.        if (e.errors) {
    67.            var message = "Errors:\n";
    68.            $.each(e.errors, function (key, value) {
    69.                if ('errors' in value) {
    70.                    $.each(value.errors, function () {
    71.                        message += this + "\n";
    72.                    });
    73.                }
    74.            });
    75.            alert(message);
    76.        }
    77.    }
    78.</script>
    Next, then template:
    01.@using System.Web.Mvc.Html;
    02. 
    03.@model KendoMVC.CostSimulatorService.Texto
    04. 
    05.@Html.HiddenFor(model => model.TextoID)
    06.<div id="divWrapper" style="width:99%; float:left; height:520px; margin-left:2px;">
    07.    <div>
    08.        @Html.LabelFor(model => model.Titulo)
    09.    </div>
    10.    <div>
    11.        @Html.TextBoxFor(model => model.Titulo, new { @class="k-textbox" , style = "width: 480px;" })
    12.        @Html.ValidationMessageFor(model => model.Titulo)
    13.    </div>
    14.    <div>
    15.        @Html.LabelFor(model => model.Corpo)
    16.    </div>
    17.    <div style="width:98%;">
    18.        @(Html.Kendo().EditorFor(model => model.Corpo)
    19.                      .HtmlAttributes(new { style = "width: 740px;height:350px" })
    20.                      .ImageBrowser(imageBrowser => imageBrowser
    21.                                                                  .Image("~/Content/Uploads/Images/{0}")
    22.                                                                  .Read("Read", "Textos")
    23.                                                                  .Create("Create", "Textos")
    24.                                                                  .Destroy("Destroy", "Textos")
    25.                                                                  .Upload("Upload", "Textos")
    26.                                                                  .Thumbnail("Thumbnail", "Textos"))
    27.                        .Messages(m => m.DialogCancel("Cancelar")
    28.                        .DialogInsert("Inserir")
    29.                        .ImageAltText("Texto alternativo"))
    30.                                                        )
    31.        @Html.ValidationMessageFor(model => model.Corpo)
    32.    </div>
    33.    <div>
    34.        @Html.LabelFor(model => model.TipoTextoID)
    35.    </div>
    36.    <div>
    37.        @Html.HiddenFor(model => model.TipoTextoID)
    38.        @(Html.Kendo().DropDownListFor(model => model.TipoTextoID)
    39.            .Name("TiposTexto")
    40.            .DataTextField("Designacao")
    41.            .DataValueField("TipoTextoID")
    42.            .BindTo((System.Collections.IEnumerable)
    43.           ViewData["TiposTexto"]))
    44.    </div>
    45.    <div style="float:left; width:155px;">
    46.        @Html.LabelFor(model => model.IsPrivado)
    47.    </div>
    48.    <div style="float:left;">
    49.        @Html.CheckBoxFor(model => model.IsPrivado)
    50.        @Html.ValidationMessageFor(model => model.IsPrivado)
    51.    </div>
    52.</div>
    The controller:
    001.using System;
    002.using System.Data.Common.CommandTrees.ExpressionBuilder;
    003.using System.IO;
    004.using System.Linq;
    005.using System.Web;
    006.using System.Web.Mvc;
    007.using Kendo.Mvc.Extensions;
    008.using Kendo.Mvc.UI;
    009.using KendoMVC.CostSimulatorService;
    010.using KendoMVC.ImageBrowser.Models;
    011. 
    012.namespace KendoMVC.Controllers
    013.{
    014.    public partial class TextosController : EditorImageBrowserController
    015.    {
    016.        #region Propriedades e Campos
    017. 
    018.        private const string ContentFolderRoot = "~/Content/";
    019.        private const string PrettyName = "Images/";
    020.        private static readonly string[] foldersToCopy = new[] { "~/Content/Uploads/Shared/" };
    021. 
    022.        #endregion
    023. 
    024.        #region CRUD
    025. 
    026.        #region ReadTextos
    027. 
    028.        public ActionResult ReadTextos([DataSourceRequest]DataSourceRequest request)
    029.        {
    030.            CostSimulatorModel modelo = new CostSimulatorModel(new Uri(@"http://localhost:53212/CostSimulatorModelService.svc/"));
    031. 
    032.            IQueryable<Texto> textos = modelo.Textos;
    033.            DataSourceResult resultado = textos.ToDataSourceResult(request);
    034.            ViewData["Textos"] = textos;
    035.            return Json(resultado, JsonRequestBehavior.AllowGet);
    036.        }
    037. 
    038.        #endregion
    039. 
    040.        #region CreateTexto
    041. 
    042.        [ValidateInput(false)]
    043.        public ActionResult CreateTexto([DataSourceRequest]DataSourceRequest request, Texto texto)
    044.        {
    045.            if (ModelState.IsValid)
    046.            {
    047.                CostSimulatorModel modelo = new CostSimulatorModel(new Uri(@"http://localhost:53212/CostSimulatorModelService.svc/"));
    048.                 
    049.                // Create a new Product entity and set its properties from the posted ProductViewModel
    050.                Texto entity = new Texto
    051.                {
    052.                    TextoID = texto.TextoID,
    053.                    Titulo = texto.Titulo,
    054.                    Corpo = texto.Corpo,
    055.                    IsPrivado = texto.IsPrivado,
    056.                    TipoTextoID = texto.TiposTexto != null ? texto.TiposTexto.TipoTextoID : texto.TipoTextoID,
    057.                    TiposTexto = texto.TiposTexto
    058.                };
    059.                modelo.AddToTextos(entity);
    060.                // Insert the entity in the database
    061.                modelo.SaveChanges();
    062.                // Get the ProductID generated by the database
    063.                texto.TextoID = entity.TextoID;
    064.                return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
    065.            }
    066.            // Return the inserted product. The grid needs the generated ProductID. Also return any validation errors.
    067.            return Json(new[] { texto }.ToDataSourceResult(request, ModelState));
    068.        }
    069. 
    070.        #endregion
    071. 
    072.        #region UpdateTexto
    073. 
    074.        [ValidateInput(false)]
    075.        public ActionResult UpdateTexto([DataSourceRequest]DataSourceRequest request, Texto texto)
    076.        {
    077.            if (ModelState.IsValid)
    078.            {
    079.                CostSimulatorModel modelo = new CostSimulatorModel(new Uri(@"http://localhost:53212/CostSimulatorModelService.svc/"));
    080. 
    081.                // Create a new Product entity and set its properties from the posted ProductViewModel
    082.                var entity = new Texto
    083.                {
    084.                    TextoID = texto.TextoID,
    085.                    Titulo = texto.Titulo,
    086.                    Corpo = texto.Corpo,
    087.                    IsPrivado = texto.IsPrivado,
    088.                    TipoTextoID = texto.TiposTexto != null ? texto.TiposTexto.TipoTextoID : texto.TipoTextoID,
    089.                    TiposTexto = texto.TiposTexto
    090.                };
    091.                // Attach the entity
    092.                modelo.AttachTo("Textos", entity);
    093.                modelo.UpdateObject(entity);
    094.                // Update the entity in the database
    095.                modelo.SaveChanges();
    096.                return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
    097.            }
    098.            // Return the updated product. Also return any validation errors.
    099.            return Json(new[] { texto }.ToDataSourceResult(request, ModelState));
    100.        }
    101. 
    102.        #endregion
    103. 
    104.        #region DestroyTexto
    105.         
    106.        public ActionResult DestroyTexto([DataSourceRequest]DataSourceRequest request, Texto texto)
    107.        {
    108.            if (ModelState.IsValid)
    109.            {
    110.                CostSimulatorModel modelo = new CostSimulatorModel(new Uri(@"http://localhost:53212/CostSimulatorModelService.svc/"));
    111. 
    112.                // Create a new Product entity and set its properties from the posted ProductViewModel
    113.                var entity = new Texto
    114.                {
    115.                    TextoID = texto.TextoID
    116.                };
    117.                // Attach the entity
    118.                modelo.AttachTo("Textos", entity);
    119.                // Delete the entity
    120.                modelo.DeleteObject(entity);
    121.                 
    122.                // Delete the entity in the database
    123.                modelo.SaveChanges();
    124.                return Json(new[] { entity }.ToDataSourceResult(request, ModelState));
    125.            }
    126.            // Return the removed product. Also return any validation errors.
    127.            return Json(new[] { texto }.ToDataSourceResult(request, ModelState));
    128.        }
    129. 
    130.        #endregion
    131. 
    132.        #endregion
    133. 
    134.        #region ImageBrowser Code
    135. 
    136.        /// <summary>
    137.        /// Gets the base paths from which content will be served.
    138.        /// </summary>
    139.        public override string ContentPath
    140.        {
    141.            get
    142.            {
    143.                return CreateUserFolder();
    144.            }
    145.        }
    146. 
    147.        private string CreateUserFolder()
    148.        {
    149.            var virtualPath = Path.Combine(ContentFolderRoot, "Uploads", PrettyName);
    150. 
    151.            var path = Server.MapPath(virtualPath);
    152.            if (!Directory.Exists(path))
    153.            {
    154.                Directory.CreateDirectory(path);
    155.                foreach (var sourceFolder in foldersToCopy)
    156.                {
    157.                    CopyFolder(Server.MapPath(sourceFolder), path);
    158.                }
    159.            }
    160.            return virtualPath;
    161.        }
    162. 
    163.        private void CopyFolder(string source, string destination)
    164.        {
    165.            if (!Directory.Exists(destination))
    166.            {
    167.                Directory.CreateDirectory(destination);
    168.            }
    169. 
    170.            foreach (var file in Directory.EnumerateFiles(source))
    171.            {
    172.                var dest = Path.Combine(destination, Path.GetFileName(file));
    173.                System.IO.File.Copy(file, dest);
    174.            }
    175. 
    176.            foreach (var folder in Directory.EnumerateDirectories(source))
    177.            {
    178.                var dest = Path.Combine(destination, Path.GetFileName(folder));
    179.                CopyFolder(folder, dest);
    180.            }
    181.        }
    182. 
    183.        #endregion
    184.    }
    185.}
    This is a copy of my StackOverflow initial post (which got 0 replies in 3 days, so I had to come here :) )

    Cheers and thanks in advance!
  2. Answer
    Vladimir Iliev
    Admin
    Vladimir Iliev avatar
    2192 posts

    Posted 30 Jul 2013 Link to this post

    Hi Nuno,

     
    I would suggest to use the default editor template for the ForeignKeyColumn ("GridForeignKey.cshtml") as an editor for the "TipoTextoID" field in the following way:

    •  Set custom editor template for the model property using UIHint attribute:
      public class Order
      {
          public int OrderID { get; set; }
          public DateTime OrderDate { get; set; }
          public string OrderDescription { get; set; }
          //set the property to use the default ForeignKeyColumn editor
          [UIHint("GridForeignKey")]
          public int EmployeeID { get; set; }
      }
    • In the custom PopUp editor template define only EditorFor:  
      @(Html.EditorFor(m => m.EmployeeID))     

     Kind Regards,
    Vladimir Iliev
    Telerik
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
  3. Stargazer
    Stargazer avatar
    2 posts
    Member since:
    Sep 2008

    Posted 30 Jul 2013 Link to this post

    Hello Vladimir!

    Thanks for the reply. I'll try that (I must confess I do not recall if I tried that already or not) and then let you know if it worked.

    [EDIT] It's working flawlessly now. Thanks, Vladimir!

    All the best,
    Nuno
  4. Manish
    Manish avatar
    5 posts
    Member since:
    Jan 2013

    Posted 30 Dec 2013 Link to this post

    Hello
    what model should i set on custom template?

    I am getting errors:

    Compiler Error Message: CS1963: An expression tree may not contain a dynamic operation

    or

    Exception Details: System.InvalidOperationException:
    The model item passed into the dictionary is of type 'System.Int32',
    but this dictionary requires a model item of type
    'SystemDashboard.ProviderMaintenanceSMS'.

    Thanks!

Back to Top