Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Child forms - detect last row? #16

Closed
maxdlx opened this issue Oct 24, 2015 · 6 comments
Closed

Child forms - detect last row? #16

maxdlx opened this issue Oct 24, 2015 · 6 comments

Comments

@maxdlx
Copy link

maxdlx commented Oct 24, 2015

Hi,

how do I detect the last row in a child form? I have a list and use the id function to index items:
id: function(e, i) {
e.idx = i+1;
return 'c3-q-' + e.idx;
},

Detecting the first child with index 1 is easy. But detecting the last child is impossible right now. How to solve this issue?

@ermouth
Copy link
Owner

ermouth commented Oct 25, 2015

First, nice to see you use id function.

For the question, there are three different approaches.

1/ You are in the DOM, so you can, using jQuery syntax, just check if your child form is the last in its parent container. It‘s not “academically” clear, but quiet effective.

2/ You can have a function inside each child form, that have acces to top levels. This approach is more general.

{
  data:{  listElts:[ /*elements of a list*/] },
  ChildFormManifest:{/* here goes child form manifest*/},
  GetRootList: function(){ return this.data.listElts},
  ui:{
    "#list":{
      data:"listElts",
      manifest: function(){
        return $.extend(true, {}, this.ChildFormManifest, {GetRootList: this.GetRootList});
      }
    }
  }
}

3/ Third approach is very similar to second, but you extend child manifest on lis init, that is faster, but less flexible. Kinda static binding.

{
  data:{  listElts:[ /*elements of a list*/] },
  ChildFormManifest:{/* here goes child form manifest*/},
  GetRootList: function(){ return this.data.listElts },
  ui:{
    "#list":{
      init: function (){ this.ChildFormManifest.GetRootList = this.GetRootList },
      data:"listElts",
      manifest: "this.ChildFormManifest"
    }
  }
}

So for 2 and 3 you have this.GetRootList() function inside each child‘s form, which returns entire array with data. Comapring child form‘s data with this.GetRootList().last() using ===, you detect, if your child form is last in the list.

@maxdlx
Copy link
Author

maxdlx commented Oct 26, 2015

Hi,
thx for your input!

I have thought about the different ways to solve it. My solution was just like your 2) using GetContent() function on the parent and comparing the index in my 'id' function.
id: function(e, i) {
e.idx = i+1;
e.firstChild = i === 0;
e.lastChild = i === this.getContent().length - 1;
return 'c3-q-' + e.idx;
},
It works, but...

When the "Add row" button triggers an 'insert' event on the list, or a row is deleted, the items do not get re-rendered. Same problem with the other approaches. The only solution would be to hack everything into a single callback and recalculate the list items on every insert/removal.

How do you solve this issue? Have you come across this in the past?

@ermouth
Copy link
Owner

ermouth commented Oct 26, 2015

the items do not get re-rendered

You mean rows are not deleted/inserted, or what? If one row has not changed, why should it re-render?

@maxdlx
Copy link
Author

maxdlx commented Oct 26, 2015

The new items are re-rendered, but the rest of the list does not notice the change. The previous "lastChild" still has the "lastChild" attribute, and I don't know how to propagate the event to all list items

@ermouth
Copy link
Owner

ermouth commented Oct 26, 2015

Do you use .hash function? It can be useful for your case, I hope.

It is used to indicate element has changed. Make it return different values if list length changed – and you will get total list re-render on add/remove, or it can depend on other events, or parent form state, or whatever.

By default, when you have not defined it explicitly, built-in hash function only changes when child form contents changed, it does not know anything about outside world. So make it know.

This default approach was chosen to avoid total list re-render on every single row changed/removed/added, that is surely ineffective for long lists.

You can also skip defining .hash and make .id function do the same – return value, dependent on list length – but this is less effective for several reasons and undesirable, if do not understand clearly, what you‘re doing.

See this example http://jquerymy.com/#CW-masterdeta – here you can drag items and see how numbers are changing during drag both in master and detail. It‘s much more tricky, but it‘s the shortset implementation of this kind of functionality I ever seen. So it can help you to go deep into things.

@maxdlx
Copy link
Author

maxdlx commented Oct 26, 2015

Thanks for the hint to 'hash' function when list length changes, I will try that!

Best regards
Chris

@maxdlx maxdlx closed this as completed Oct 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants