This is a migrated thread and some comments may be shown as answers.

Adding ListView to EditorTemplate

8 Answers 347 Views
Scheduler
This is a migrated thread and some comments may be shown as answers.
Simon
Top achievements
Rank 1
Simon asked on 04 Jan 2018, 02:32 PM

Using the scheduler-custom-editor project as a guide I've created a custom editor template and have added a number of fields as needed for our project. One of these is a Kendo ListView that I used in another project to retrieve a number images from a web service. This all seems to be working fine but one thing I'm stuck on is writing the filename of the clicked image to a text field on the template (see screenshot). Relevant template code is:

 

<div class="k-edit-label">
    Image Details
</div>
<div class="eventimage-section k-content wide">
    <div id="listView" class="k-edit-field"></div>
    <div id="pager" class="k-pager-wrap"></div>
</div>


<script type="text/x-kendo-template" id="template">
    <div class="eventimage">
        <img src="http://nsccapi/eventimages/\\#= FileName \\#" alt="\\#: FileName \\# image" />
            <h3>\\#: FileName \\#</h3>
        </div>
</script>

<script>

var dataSource = new kendo.data.DataSource({
    transport: {
        read: {
            url: "http://myapi/api/events/allimages",
            dataType: "jsonp"
        }
    },
    pageSize: 3
});

$("\\#pager").kendoPager({
    dataSource: dataSource
});

$("\\#listView").kendoListView({
    dataSource: dataSource,
    selectable: "single",
    @* change: onChange,*@
    template: kendo.template($("\\#template").html()),
    autoBind: false
});

dataSource.read(); // "read()" will fire the "change" event of the dataSource and the widget will be bound

@* function onChange() {

//    var data = dataSource.view(),
//        selected = $.map(this.select(), function (item) {
//            var sel = data[$(item).index()].FileName;
//            $("\\#ImagePath").val(sel)
//            return sel;
//        });

    } *@



</script>

 

The ListView renders the images as expected but the change event (change: onChange) of the listview fails saying that onChange is not defined. I've commented it out in my code as shown above. #ImagePath is the id of the text field I wish to write to. Am I going about this the correct way? Should I instead handle a click event on an image and grab it's filename from the <h3> tag?

Thanks.

 

8 Answers, 1 is accepted

Sort by
0
Dimitar
Telerik team
answered on 08 Jan 2018, 11:50 AM
Hello Simon,

The correct way to achieve the desired result would be to initialize and configure the ListView by using the data attributes (where attendees is a collection in the Scheduler DataSource):
// ListView in the custom Editor
<div class="eventimage-section k-content wide">
  <div data-role="pager" data-bind="source: attendees"></div>
  <div data-role="listView" data-bind="source: attendees" data-template="template-listview" data-change="onChange"></div>
</div>

The ListView template can be place outside of the Scheduler's edit template:
<script id="event-template" type="text/x-kendo-template">
  ...
</script>
 
<script type="text/x-kendo-template" id="template-listview">
  <div class="eventimage">
    <img src="../content/web/foods/#= ImageID#.jpg" alt="#: ImageName# image" />
    <h3>#= data.ImageName #</h3>
  </div>
</script>

This way, you should be able to correctly bind the change event as follows:
<script>
  function onChange(e) {
    console.log("lv change");
  }
       
  $(function() {
    $("#scheduler").kendoScheduler({...})
  })
</script>


Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Simon
Top achievements
Rank 1
answered on 08 Jan 2018, 02:06 PM

Ok I see where you are going, however the images that are the datasource of the ListView are retrieved from a web service, they are not a collection on the ViewModels that are the Datasource of the Scheduler. 

The idea is that the user chooses a single image from he ListView (hence the onClick function) to designate that as the image for the event, there isn't a collection of images for the event, just a single image:

From my ViewModel:

    public class EventScheduleViewModel : ISchedulerEvent
    {

......

        [StringLength(512)]
        [Display(Name = "Event Image")]
        public string ImagePath { get; set; }

        [StringLength(100)]
        [AltTextRequired(ImageField = "ImagePath", ErrorMessage = "Image Alt Text is required when adding an image for the event.")]
        [Display(Name = "Image Alt Text")]
        public string ImageAltText { get; set; }

     ...

}

Are you suggesting that I make this collection of images a property of my ViewModel so that data-bind="source: attendees" becomes something like data-bind="source: eventimages"? 

0
Accepted
Dimitar
Telerik team
answered on 10 Jan 2018, 07:24 AM
Hello Simon,

Your assumption is correct. The suggested approach would require the event images to be a collection of the Scheduler ViewModel.

Alternatively, the same behavior can be achieved by initializing the ListView in the Scheduler's edit event as follows:
<script>
edit: function(e){
  var dataSource = new kendo.data.DataSource({
    transport: {
      read: {
        dataType: "jsonp"
      }
    },
    pageSize: 3
  });
                             
  setTimeout(function() {
    $("#pager").kendoPager({
      dataSource: dataSource
    });
 
    $("#listView").kendoListView({
      dataSource: dataSource,
      selectable: "single",      
      template: kendo.template($("#template").html()),
      change: function(e) {
        console.log("ListView Change Event");
      }                   
    });             
  });                     
}
</script>

Checkout the following Dojo example, where the above approach is demonstrated. With it, the change event of the ListView is executed successfully and a message is being logged in the browser console to signify this.

Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Simon
Top achievements
Rank 1
answered on 10 Jan 2018, 12:47 PM

Dimitar, thank you for the suggestion, it's working great now. I implemented it in the edit event of the Scheduler as you described, that keeps my ViewModel clean. I had been trying to manage a number of project requirements on the CustomEditorTemplate but managing things in the edit event of the Scheduler seems to be a much better approach.

I'm guessing the use of setTimeout allows some time for the loading of the data from the web service to occur before the ListView uses it as its datasource?

Thanks again for your help with this, great stuff.

Simon

 

0
Dimitar
Telerik team
answered on 11 Jan 2018, 08:10 AM
Hello Simon,

I am glad to hear that the issue is resolved successfully.

The edit template of the Scheduler is nested inside a Kendo UI Window. The reason why the setTimeout() is needed is because the edit event of the Scheduler is triggered before the Window is opened. By using the setTimeout(), we make sure that the Window widget is opened and the ListView and Pager DOM elements are available. 

Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Simon
Top achievements
Rank 1
answered on 12 Jan 2018, 02:15 PM

Ok, still a couple of issues with this approach. When the user selects an image from the kendoListView, the change function fires and I write the filename of the selected image to the ImagePath text field on the editor template:

....

 

                    var data = dataSource.view(),
                        selected = $.map(this.select(), function (item) {
                            var sel = data[$(item).index()].FileName;
                          //  console.log(sel);
                            $("#ImagePath").val(sel);

....

 

 

<div class="k-edit-label">
    @(Html.LabelFor(model => model.ImagePath))
</div>
<div data-container-for="imagepath" class="k-edit-field">
    @(Html.TextBoxFor(model => model.ImagePath, new { @class = "k-textbox", data_bind = "value:ImagePath" })) <a href="\\#" id="clearImage">Clear</a>
</div>

 

Problem is the Model does not get updated, and this value of the ImagePath textbox is not posted when Save is clicked. In fact if this is the only change the user makes on edit of an existing event then the Update method on the associated controller never gets called as there has not been any change to the Model. I've checked the Request.Form property in a debug session and no value is posted.

How can I update the Model in this scenario and make sure the Update controller method is invoked? Can I update the model "manually" in the edit event of the scheduler before the form is posted?

 

Thanks,

Simon

 

0
Simon
Top achievements
Rank 1
answered on 12 Jan 2018, 03:33 PM

This seems to work:

 

    function scheduler_save(e) {
        e.event.ImagePath = $("#ImagePath").val();
        e.event.dirty = true;
    }

Had to set dirty to true on the model to force an update, maybe not ideal but I can live with it.

 

0
Dimitar
Telerik team
answered on 15 Jan 2018, 09:44 AM
Hello Simon,

In the described scenario you have adopted the correct approach to force an update by modifying the dirty flag of the event model. You can checkout the Model API Reference for additional information:


Regards,
Dimitar
Progress Telerik
Try our brand new, jQuery-free Angular components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
Scheduler
Asked by
Simon
Top achievements
Rank 1
Answers by
Dimitar
Telerik team
Simon
Top achievements
Rank 1
Share this question
or