10 Replies Latest reply on Nov 11, 2019 6:26 PM by DaveArch

    How to Fetch Attribute of Collection using Key

    DaveArch

      Node: 12.13.0

      Jet: 7.2.0

       

      Scenario: Trying to fetch attribute of collection from selected table row. I have the selected.row attribute bound to an observable and the on-selection-changed attribute set to a method in my VM.  When the method fires, I fetch they key from the selectedRows observable but I am struggling with how to query the collection for the key and fetch the attributes for the row.  I have re-produced this with an emp/dept example to highlight.

       

      When trying to use the 'get' method on the Model class I am receiving 'xx is not a function'.

       

      Any help greatly appreciated.

       

      HTML:

       

      <oj-table id='table' aria-label='Employee Table' data='[[employeeDataSource]]'

          selection-mode='{"row": "single", "column": "none"}' dnd='{"reorder": {"columns": "enabled"}}'

          scroll-policy='loadMoreOnScroll' scroll-policy-options='{"fetchSize": 10}'

          selected.row='{{selectedRows}}'

          on-selected-changed='{{selectedChangedListener}}'

          columns='[{"headerText": "Employee Id",

                   "field": "EmployeeId",

                   "headerClassName": "oj-sm-only-hide",

                   "className": "oj-sm-only-hide",

                   "resizable": "enabled"},

                  {"headerText": "First Name",

                   "field": "FirstName",

                   "resizable": "enabled"},

                  {"headerText": "Last Name",

                   "field": "LastName",

                   "headerClassName": "oj-sm-only-hide",

                   "className": "oj-sm-only-hide",

                   "resizable": "enabled"},

                  {"headerText": "Salary",

                   "field": "Salary",

                   "resizable": "enabled"}]' style='width: 100%; height: 200px;'>

        </oj-table>

       

      ViewMode:

       

        function DashboardViewModel() {

       

          self.selectedRows = new keySet.ObservableKeySet();

          self.selectedRowsModel = ko.observable();

       

         

            self.employeeDataSource = ko.observable();

            self.employeeDataSourceURL = 'http://<host>/restapp/rest/1/Employees';

           

            /* List View Collection and Model */

            var employeeModelItem = oj.Model.extend({

              idAttribute: 'EmployeeId'

            });

       

       

            self.employeeCollection = new oj.Collection.extend({

              url: self.employeeDataSourceURL,

              fetchSize: 25,

              model: employeeModelItem,

              oauth: new self.myBasicAuth()

            });

           

            self.employeeTable = ko.observable(new self.employeeCollection());

            self.employeeDataSource(new oj.CollectionTableDataSource(self.employeeTable()));

       

            self.selectedChangedListener = function(event)

            {

              var data = event.detail;

              var selectionText = '';

              var keys = '';

              var fName = '';

       

              if (event.type == 'selectedChanged')

              {

                  if(self.selectedRows() != null && self.selectedRows().values().size > 0){

       

                    self.selectedRows().values().forEach(function(key)

                      {

                          console.log("Selected Key: " + key);

       

                          // Attempt 1

                          var emp = self.employeeTable().get(key);

                         

                          // Error: Raises emp is not a function

                          fName = emp().get('FirstName');

                         

                          // Attempt 2

                          self.selectedRowsModel(self.employeeTable().get(key));

                         

                          // self.selectedRowsModel(...).get is not a function

                          fname = self.selectedRowsModel().get('EmployeeId');

       

                      });

                  }

                }

       

       

            }

           

            return new DashboardViewModel();

           

           }

        • 1. Re: How to Fetch Attribute of Collection using Key
          Duncan Mills-Oracle

          As you are using a single selection you can take advantage of the first-selected-row attribute on the table - when you select a row, an observable bound to this attribute will be updated with the row information in the form of an object with two attributes: 1

          1. key (Any) The row key

          2. data (row) The full row of data 

          So in fact you can dispense with the on-* event and just directly monitor the variable you have bound to the firstSelectedRow and get direct access to the row without having to do a secondary lookup

          • 2. Re: How to Fetch Attribute of Collection using Key
            DaveArch

            Hi Duncan

             

            Thanks for your reply.

             

            When I use first-selected-row with on-selection-changed, the observable is undefined at the point the function is called:

             

            HTML:

              <oj-table id='table' aria-label='Employee Table' data='[[employeeDataSource]]'

                selection-mode='{"row": "single", "column": "none"}' dnd='{"reorder": {"columns": "enabled"}}'

                scroll-policy='loadMoreOnScroll' scroll-policy-options='{"fetchSize": 10}'

                first-selected-item="{{firstSelectedItem}}"

                on-selected-changed='{{selectedChangedListener}}'

                columns=...>

              </oj-table>

             

            VM:

              self.selectedChangedListener = function(event){ 

                console.log("FSI: " + self.firstSelectedItem()); // undefined

              }

             

            Is this because selectedChangedListener has fired before firstSelectedItem is set?

             

            Thanks!

            • 3. Re: How to Fetch Attribute of Collection using Key
              Duncan Mills-Oracle

              As I said rather than using the on-selected-changed you can instead listen for a change on the variable bound to first-selected-item - e.g. create a KO.computed or use the KO subscribe feature to execute code whenever the firstSelectedItem observable is changed.

              • 4. Re: How to Fetch Attribute of Collection using Key
                DaveArch

                Removed on-selected-change and subscribed to observable using computed function but the row change doesn't seem to be being pushed through to the model.  The console log output gets written when the table renders (firstSelectedItem is undefined) then does not update when the row changes.

                 

                HTML:

                  <oj-table id='table' aria-label='Employee Table' data='[[employeeDataSource]]'

                    selection-mode='{"row": "single", "column": "none"}' dnd='{"reorder": {"columns": "enabled"}}'

                    scroll-policy='loadMoreOnScroll' scroll-policy-options='{"fetchSize": 10}'

                    first-selected-item="{{firstSelectedItem}}"

                    columns=...>

                  </oj-table>

                 

                VM:

                  self.firstSelectedItem = ko.observable();

                  self.listenSelectedRow = ko.computed(function() {

                         

                    console.log("FSI Computable: " + self.firstSelectedItem());

                     

                  }, this);

                • 5. Re: How to Fetch Attribute of Collection using Key
                  Duncan Mills-Oracle

                  Have you checked that self in the context of that computed function is actually what you expect it to be?

                   

                  It will probably be easier for you to just use a subscribe function

                   

                  self.firstSelectedItem = ko.observable();

                  self.firstSelectedItem.subscribe(function(newSelectionValue){ console.log("FSI Computable: " + JSON.stringify(newSelectionValue));});

                  1 person found this helpful
                  • 6. Re: How to Fetch Attribute of Collection using Key
                    DaveArch

                    Duncan - thank you for your continued replies here.

                     

                    The subscription is not being called when the row changes.

                     

                    HTML:

                      <oj-table id='table' aria-label='Employee Table' data='[[employeeDataSource]]'

                        selection-mode='{"row": "single", "column": "none"}' dnd='{"reorder": {"columns": "enabled"}}'

                        scroll-policy='loadMoreOnScroll' scroll-policy-options='{"fetchSize": 10}'

                        first-selected-item="{{firstSelectedItem}}"

                        columns=...>

                      </oj-table>

                     

                    VM: 

                          self.firstSelectedItem = ko.observable();

                          self.firstSelectedItem.subscribe(function (newSelectionValue) {

                            console.log("Selected Item Subscribe: " + JSON.stringify(newSelectionValue));

                          });

                     

                    If I manually update the value of the observable in another function, the subscription is called and the new value is seen in the console.

                    • 7. Re: How to Fetch Attribute of Collection using Key
                      Duncan Mills-Oracle

                      I've written a Fiddle for you that shows it working:

                       

                      https://jsfiddle.net/drmills/w3ubmdfy/14/

                      This prints the selected row to the page via the observable and to the console via a subscribe()

                       

                      Just make sure you're not being caught out by something silly like your JS console filtering to show errors only

                      • 8. Re: How to Fetch Attribute of Collection using Key
                        DaveArch

                        Duncan - thank you for taking time to do the jsfiddle example.


                        Whilst this works where the data is sourced from an ArrayDataProvider, it does not work for me if the data is sourced from oj.Collection where I'm fetching the data from a service.

                         

                        Below is a screen shot of your jsfiddle example alongside my table sourced from employeeDataSource as detailed in the original post.

                         

                        first-selected-rows.PNG

                        • 9. Re: How to Fetch Attribute of Collection using Key
                          Duncan Mills-Oracle

                          DataSources have been deprecated and replaced with DataProviders so you should be using a CollectionDataProvider in. 7.2.0 anyway  - However this can be constructed from a collection in the same way...

                          This stuff all works fine no matter what the data provider is - as long as a idAttribute has been defined on the underlying model - which you have done.

                          1 person found this helpful
                          • 10. Re: How to Fetch Attribute of Collection using Key
                            DaveArch

                            Hi Duncan

                             

                            first-selected-item works perfectly when using CollectionDataProvider as you said so we will use this approach given the Jet version.

                             

                            For future referers to this post, first-selected-item does not work with oj.CollectionTableDataSource

                             

                            Thanks for your help with this - much appreciated.

                             

                            David