jQuery UI Widgets Forums Grid Foreign key column Display field with knockout observable array source

This topic contains 1 reply, has 1 voice, and was last updated by  Velislav Gebrev 10 years, 5 months ago.

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author

  • Velislav Gebrev
    Participant

    Hi,

    I’m currently evaluating jqxGrid for use in an SPA project that is built using Durandal and Breeze.

    I have the following viewmodel

    var carsViewModel = function() {
      var self = this;
      this.entityManager = new breeze.EntityManager("breeze/cardata");
      this.activate = function() {
        self.loadData();
      }
      this.loadData = function() {
        var makesQuery = breeze.EntityQuery.from("Makes").using(self.entityManager);
        var carsQuery = breeze.EntityQuery.from("Cars").using(self.entityManager);
        var queryExecution = [makesQuery.execute(), carsQuery.execute()];
        Q.all(queryExecution).then(self.bindGrid).fail(self.dataError);
      }
      this.bindGrid = function (data) {
        var gridSource = {
          datatype: "observablearray",
          datafields: [
            { name: 'CarId' },
            { name: 'MakeId' },
            { name: 'Name' }
          ],
          updaterow: function (rowid, newdata, commit) {
            commit(true);
          },
          deleterow: function (rowid, commit) {
            commit(true);
          },
          localdata: data[1].results
        };
        var dataAdapter = new $.jqx.dataAdapter(gridSource);
        var grid = $("#carsGrid");
        grid.jqxGrid({
          source: dataAdapter,
          sortable: true,
          editable: true,
          filterable: true,
          columns: [
            { text: 'ID', datafield: 'CarId', editable: false },
            { text: 'Name', datafield: 'Name', columntype: 'textbox' },
            { text: 'Make', datafield: 'MakeId', columntype: 'dropdownlist' }
          ]
        });
      }
      this.dataError = function(error) {
        alert('error');
      }
    };

    Works great, the Breeze entity manager fetches my entities from the back-end, sorts out the Car-Make relationship and presents me with a knockout observable array to bind to the grid. The Make column drop-down in the grid correctly gives me the list of Makes.

    Now, I want to actually display the Make Name rather than its Id in that column. I’ve gone through the key/value and fk column demos and the API docs for both jqxGrid and jqxDataAdapter widgets and all the examples I could find showing how to use JQWidgets with Breeze and Knockout but I just can’t seem to get it to work.

    Could you please provide some guidance as to how I can show the Make Name, instead of its Id, taking into consideration that the underlying data is a Knockout observable array of Breeze entities, and I don’t want to break any of their functionality?

    Thank you and kind regards,
    Veli


    Velislav Gebrev
    Participant

    So I got it to work in the end, but it feels incredibly hacky.
    Please tell me there’s a better way to do this than this:
    1. Create a whole new jqxDataAdapter for the makes
    2. Add a new datafield MakeName to the main data adapter to be used for as display field for the MakeId column
    2a. This then requires the breeze entity to be extended because, on update, it looks like the grid tries to set the value of a non-existing MakeName property on the underlying entity.
    3. Create my own dropdownlist editor bound to the Makes data adapter on my grid column

    That’s over 20 lines of js code just to set a display member on FK column! It cannot be the correct way to do this. I mean the grid by default seems to be aware of the relationship (it creates the dropdownlist with the right set of entities – just displays their IDs).

    I will try to play around with things like the mapping. In the meantime, here’s the ugly working code (also note that the dataadapter’s localdata must actually be an observablearray, not simply the result of the breeze query – an oversight which didn’t help my confusion :P)

    var carsViewModel = function() {
      var self = this;
      this.entityManager = new breeze.EntityManager("breeze/cardata");
      this.activate = function() {
        self.loadData();
      }
      this.loadData = function() {
        var store = self.entityManager.metadataStore;
        store.registerEntityTypeCtor('Car', function () {
          this.MakeName = ko.observable();
        });
        var makesQuery = breeze.EntityQuery.from("Makes").using(self.entityManager);
        var carsQuery = breeze.EntityQuery.from("Cars").using(self.entityManager);
        var queryExecution = [makesQuery.execute(), carsQuery.execute()];
        Q.all(queryExecution).then(self.bindGrid).fail(self.dataError);
      }
      this.getMakesDataAdapter = function(entities){
        var observableEntities = ko.observableArray(data);
        var makesSource = {
          datatype: "observablearray",
          datafields: [
            { name: 'MakeId' },
            { name: 'Name' }
          ],
          localdata: observableEntities
        };
        return new $.jqx.dataAdapter(makesSource, { autobind: true });
      }
      this.bindGrid = function (data) {
        var makesDataAdapter = self.getMakesDataAdapter(data[0].results);
        var carsObservable = ko.observableArray(data[1].results);
        var gridSource = {
          datatype: "observablearray",
          datafields: [
            { name: 'CarId' },
            { name: 'MakeName' }, value: 'MakeId', values: { source: makesDataAdapter.records, value: 'MakeId', name: 'Name' } },
            { name: 'MakeId' },
            { name: 'Name' }
          ],
          updaterow: function (rowid, newdata, commit) {
            commit(true);
          },
          deleterow: function (rowid, commit) {
            commit(true);
          },
          localdata: carsObservable
        };
        var dataAdapter = new $.jqx.dataAdapter(gridSource);
        var grid = $("#carsGrid");
        grid.jqxGrid({
          source: dataAdapter,
          sortable: true,
          editable: true,
          filterable: true,
          columns: [
            { text: 'ID', datafield: 'CarId', editable: false },
            { text: 'Name', datafield: 'Name', columntype: 'textbox' },
            { text: 'Make', datafield: 'MakeId', displayfield: 'MakeName', columntype: 'dropdownlist',
              createeditor: function (row, value, editor) {
                editor.jqxDropDownList({ source: insuranceTypeAdapter, displayMember: 'Name', valueMember: 'MakeId' });
              }
            }
          ]
        });
      }
      this.dataError = function(error) {
        alert('error');
      }
    };
Viewing 2 posts - 1 through 2 (of 2 total)

You must be logged in to reply to this topic.