View and Referential Fields (Entities)

Abstract

In this tutorial we'll learn to load and display referential data that is usually required to be displayed with primary data fields.

Keywords: WindnTrees,CRUD,CRUDS,CRUD2CRUD,Reference fields, Referential fields
  • Strategy

    To achieve tutorial objectives we'll use project from View & Related Lists and make few changes.

    We'll extend (or define):

    1. EntityRepository constructor with related objects (Category,SkillLevel).
    2. Javascript object model Topic with Category and SkillLevel fields.
    3. Knockout view model and change update() with updateRecord().
    4. Script to remove referential objects from request against update CRUD method.
    5. HTML view

    Extend Repository

    Change EntityRepository constructor definition and override appropriate functions as follows:

    public TopicRepository(TutorialsContext dbContext, string relatedObjects = "Category,SkillLevel", bool enableLazyLoading = false)
                : base(dbContext, relatedObjects, enableLazyLoading)
            {  }
    
    protected override Topic PostCreate(Topic contentObject)  {
    
                //Following is required if you want to load referential data 
                //against main entity in create CRUD call.
                var category = (new TutorialsContext()).Category.Where(l => l.Uid == contentObject.CategoryId).SingleOrDefault();
                if (category != null)
                {
                    contentObject.Category = category;
                }
    
                var skillLevel = (new TutorialsContext()).SkillLevel.Where(l => l.Uid == contentObject.SkillLevelId).SingleOrDefault();
                if (skillLevel != null)
                {
                    contentObject.SkillLevel = skillLevel;
                }
                return base.PostCreate(contentObject);
           }
    
  • Extend WindnTrees View

    Extend CRUDView as following:

            //extended method to remove referential fields 
            //you may omit following definition and use original
            //update() function according to your requirements
            view.getObserverObject().updateRecord = function () {
    
                //get reference to WindnTrees form object
                var entityObject = view.getObserverObject().getFormObject();
    
                //remove referential fields to get in compliance with 
                //server side action method
                entityObject.Category = null;
                entityObject.SkillLevel = null;
    
                //make create CRUD call with corrected content object
                view.getObserverObject().create({ content: entityObject });
            };
    
  • Update Javascript Object Model

    Update javascript object model "Topic" to include Category and SkillLevel fields.

        //category reference object
        instance.Category = data.Category;
        //skill level reference object
        instance.SkillLevel = data.SkillLevel;
    

    Knockout View Template

    Update knockout view with following code:

    <script type="text/html" id="listitem">
        <li>
            <div class="row align-items-center">
                <div class="col-sm-12 col-md-6 col-lg-6 order-0">
                    <!--Topic Subject-->
                    <div class="d-flex justify-content-start"><a href="#topic-detail" data-toggle="collapse" 
    data-bind="attr: { id: Uid, href: '#topic-detail' + Uid }"><h3 class="mt-3"><span 
    data-bind="text: Subject()"></span></h3></a></div>
                </div>
                <div class="col-sm-12 col-md-6 col-lg-6 order-0">
                    <span class="d-flex justify-content-end">
                        <!-- ko if: (Category !== null && Category !== undefined) -->
                        <span>Category: </span>
                        <em>
                            <span data-bind="text: Category.Title "></span>,
                        </em>
                        <!-- /ko -->
                        <!-- ko if: (SkillLevel !== null && SkillLevel !== undefined) -->
                        <span>Skill Level: </span>
                        <em>
                            <span data-bind="text: SkillLevel.Title "></span>
                        </em>
                        <!-- /ko -->
                    </span>
                </div>
            </div>
    
                <div class="row">
                <div class="col-sm-12 col-md-12 col-lg-12">
                    <!--Menu-->
                    <div class="pb-2">
                        <span data-bind="text: Menu()"></span>
                    </div>
                    <div id="topic-detail" class="collapse" data-bind="attr: { id: 'topic-detail' + Uid }">
                        <!--Description1-->
                        <div data-bind="html: Description1()"></div>
                        <!--Description2-->
                        <div data-bind="html: Description2()"></div>
                        <div class="row">
                            <div class="col-sm-12 col-md-6 col-lg-6">
                                <div class="d-flex justify-content-start">
                                    <!--UpdateTime-->
                                    <span data-bind="text: UpdateTime()"></span>
                                </div>
                            </div>
                            <div class="col-sm-12 col-md-6 col-lg-6">
                                <!--list action fields-->
                                <div class="d-flex justify-content-end">
                                    <a class="green p-2" href="#" 
    data-bind="click: function(data, event) { $parent.resetFormForEditing($index); }" data-toggle="modal" data-target="#__form" 
    title="Edit"><i class="fa fa-edit text-success"></i>Edit</a>
                                    <a class="red p-2" href="#" data-bind="click: function(data, event) { $parent.delete($data); }" 
    title="Delete"><i class="fa fa-times text-danger"></i>Delete</a>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </li>
    </script>
    
  • HTML Form View

    Now complete HTML Form view as follows:

                <div id="__form" class="modal fade" style="display: none;">
                <div class="modal-dialog modal-dialog-centered" style="min-width: 800px;">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h4 class="col order-0">
                                <span class="d-flex justify-content-start" 
    data-bind="text: getEditMode() ? getEditModeCaption() : getNewModeCaption()"></span>
                            </h4>
                            <div class="col order-1">
                                <span class="d-flex justify-content-end">
                                    <button type="button" data-dismiss="modal"><span>×</span></button>
                                </span>
                            </div>
                        </div>
    
                            <div class="modal-body">
                            <div class="row">
                                <span class="col-sm-12 col-md-10 col-lg-10 order-first result" 
    data-bind="template: {name: 'results_messages'}"></span>
                                <span class="col-sm-12 col-md-2 col-lg-2 order-last status" 
    data-bind="template: {name: 'results_processing'}"></span>
                            </div>
                            <div class="row" data-bind="if: Errors().length > 0">
                                <div class="col-sm-12 col-md-12 col-lg-12">
                                    <ul class='errorlist' data-bind="template: {name: 'list_error_messages' , foreach: Errors}"></ul>
                                </div>
                            </div>
                            <div data-bind="with: getFormObject()">
                                <div data-bind="template: {name: 'formcontent' }"></div>
                            </div>
                        </div>
                        <div class="modal-footer">
                            <span class="d-flex justify-content-end">
                                <button type="button" id="btnCloseAddForm" class="btn btn-default" 
    data-dismiss="modal"><span>Close</span></button>
                                <!-- invokes create, update method to save new and existing record. -->
                                <!-- create/update are CRUD methods that are integrated in View (CRUDView) and 
    linked with Observer (CRUDObserver composed of observables). -->
                                <button type="button" data-bind="click: function() { getEditMode() ? updateRecord() : create(); }" 
    id="btnAddEdit" class="btn btn-primary"><span>Save</span></button>
                            </span>
                        </div>
                    </div>
                </div>
            </div>
    
  • Summary

    WindnTrees CRUDS provide efficient means of loading, processing and displaying referential data. Download the complete project here.