 Hello! So as is the right thing to do when making a presentation, I spent three-quarters of the time choosing the right image for the front page and I think I found the right page for the right image for a talk about grids on ember. I can't think of a better image than that for an ember grid. Literally two hours of my afternoon until I found that. I have been working at Ember now for years and since the very early days. Building content management tool mainly for digital signage around the world. That contains a lot of tables – tables of players, tables of content, tables of users, tables of roles for users – all sorts of different things. I've found it really frustrating doing an HTML table. Y gallwn ychydig yma ymlaen yn ymlaen y Tafel. Gwyddiad yn brydd yma, ond rydyn ni'n gweld yn fwy. Rydyn ni'n rwyf yn gweithio yn y pethol. Rydyn ni'n gweithio, rydyn ni'n gweithio yn y pethol. Llywodraeth ymlaen yn y pethol yn y pethol, yn y porwych ymlaen i gilydd o'r gwybodaeth i'r cyfrifodau a'r llwyll. Rydyn ni'n gweithio'n gweithio'n gweithio i'r llwydd. Rydyn ni'n gweithio'n gweithio. dda ni'n gweld. Diolch i chi am hyn. Silver Curve is an agency based in Camden Town. We have our own rendering technologies for Raspberry Pi, graphics rendering. We do third-party consultancy work for digital language companies, mobile apps, back ends, full stack, all sorts of different things. Ieith elongol eistedd mydwyr cymuned a'r blaen i'wch cerddwordy'r Rhifaeliau. Mae'r llwythden yn ysgrif iawn byw, i'w cymryd gwirioneddau yma. Felly, cyfiaws. Rydw i ymddian nhw a rydw i'n mynd yn gwneud yma. Mae'r llyfr yn meddwl i'r ffordd gyda glen. Rydw i'n meddwl i'r borig o'i gilydd. Dwi'n gynradwch. Felly mae'n ganddo'r bydd y cael unedig gwaith, ac rhaid i gyd yn y felly gonfa a ddim gweithio chi y gallwn gwneud yn ychydig yn ei amser, ac mae'n gweithio yn erbyn bod y bydd yn gyd yn ei gyd yn ychydig, ac mae'n ei gweithio'n gweithio'n gweithio. Yeist yn cael ei wneud i'r pob o'r ddataeth a'r gyfnodol a'r gwneud a'r hanghau ar ddau. Nid oes, roeddwn yn deud yn gweithio'n gweithio. If we look at tables and embers, let's look at a couple of ways of doing it, we could just start with a table and say we're going to put some header cells in, and then for each row we're going to put some body cells in. And that works, but what if I wanted to put some data on the header as well as on the row? We're now going to make sure that my cells are on the same order in my header in my row ac mae'n gymble o'r cynig pan mae ein cyfnod yn gyntgen fod yn ystyr这么ol, ein gwn i'r ddweud y cerddol yn eisio ar hyn yn gynnwys iawn. Gwydai i wychelwyd fod yna ni'n gweld ac ewbent ar y lleeddor, y gallwch chi'n ffordd gynghori, yn ystod y cwmplio amddir yma, mewn y llysdydd pwyd, a'r llythdoedd arall yn llysdydd pwyd. Felly yma'r gwneud hynny i'ch ei meddwl, fel y llysydd y cwmplion hwn yn eich cyfrifol, component these days. So you're actually returning a list of objects from your controller, which determine how that table is rendered. If you've got three or four tables on your form, you might have 500, 600 lines of code just returning the declarative objects of how you want your columns to be. And that's doable, and you could generate that from data, but I don't like generating the look of the page in the JavaScript. I want to generate the look of the page in my template. That's what the HBS file is for. So the other problem with that apart is that it's based on views, not components, and this project started from a discussion between two or three of us saying, well, we all want this to be components. Let's go and rewrite it. And there were some starting points, two or three forks, where they started to refactor it. And actually found it was really difficult to refactor because it was all based around the way views worked, and components worked differently. And it just got to be really nasty. And I stood up and said, look, I'm going to go and start a new one who's with me. And somebody in Berlin, Sean C, decided he was with me, and we had a bit of a Skype call and kind of something better. So what we said is the data comes from the code, the layout comes from the template in your component structure, and we'll use the components to define the layout. And that sounded really, really easy. And in the next four hours of Skyping, we realized it really wasn't. So the two of us have led this. We've now got Andy Pie is coming in as well as of today. We've got two or three other people who are coming on board as well. And we'd like some more contributors because there are lots of things we want to do with this, and it's way bigger than two people can handle. So if we look at the original problem, this is how we started. So we said, OK, we'll have an Enbergrid component. We'll have a header component which will have a list of cells. I've only got one cell in here, just to make it easy. And then we've got a body section, and that will have a row component with a series of cells, and we could do in each row on our data to generate a whole list of row components. And then each cell could use the data and format it differently. I could have an image cell, a data cell, an editable cell, a star cell, whatever. The problem is that you start repeating the data. So if you want your columns to line up, you have to make sure the width in your header cell and your body cell are the same. If you want to have draggable column borders, that becomes even nastier. So we gave up that idea and said, OK, we can't define by rows. We're going to have to define by columns. So let's define it by columns. So we've got a column component with a width, but only one width now. And in there, we have a header component and a body component. And that's great. Except that when we render it, we want to render rows. So you don't have a one-to-one mapping between the components you want to write in your template and the way you'd actually want to generate the DOM. So we get this error popping up all over the place, and I've no idea, I suggest Hint, I think, came up with it, but we got rid of it very quickly. The delete key works wonders here. So you can't have a table that has rows and columns that is rendered directly from components, where the components you write map to the components of the render and is nice to use. It's not possible. So new HTML component we've come up with, thanks to the wonders of web components. The component you use in your template and you write doesn't have to be the one that renders your content. And this is where we started to redefine things. We came across a couple of other projects that were doing similar things and took some borrowed and not stole some ideas from them. And I think that the hat McGandy said it best, be the component you wish to see in the world. So this is what we ended up with, and the wrapping on that is disgusting. So I apologise for that. So we have an embryo component, and that contains a list of column components. Those can optionally have a header, a body and a footer inside them. There's some default behaviour if you don't put them in. And then there's a model that goes with each column that is the data associated with that column. For example, the width. So that's what you would work with in your template. Behind the scenes, we then have a nested EG render set of components. So we have an EG header, an EG header cell, and a resize handle for the header cell. Then we have a body component, which contains rows, which contains cells and an optional footer, which contains footer cells. Now, those components you would never use when you actually use Ember Grid. You would use the top set, the black ones, and it will generate the green ones for you. And sitting in the middle between them is the column model. So these components, the header, the body, the footer that you define on a column, will write their configuration into the column model. And then the header cell component will read its width, for example, from the column model, as will the body cell and the footer cell. So if you drag, using the resize handler, what that will do is edit the width on the column model, which is then bound to the width on all three of the header, footer and body. So that works quite well for data. But now I want to say, well, I want to be able to custom render my component. I want to be able to put in my own image tag or my own component within that body cell. And what we've realised, there's a one of component called Ember wormhole, which you define a component within, and then you say, I want that component to appear somewhere completely different. And it will change the parent on the DOM element and move it somewhere else. We've taken that to the end of the degree, and we've actually stuck the content that you put inside your block into that model. So now it can be reparented into one of these later on. And if you can understand that, your brain is in better shape than mine was at the time. So we then want to get infinite scrolling. We want to have a million rows in our grid. So we've got Ember collection for that, which I don't know if you come across. It's the new Ember list for you. It's in beta, but it's pretty good. And what we're using is the body section. We'll delegate to Ember collection, and then we give Ember collection our body rows for it to render. And then it deals with reusing DOM inside and outside the scrollable region. So let's go into the fun bit. I'll start by demonstrating what we've got. So this is our GitHub pages. So if we go to a minimal one, first of all. Is that big enough? Someone in the front row says yes. I like that. So our minimal one. We have a list of data objects. I think we've created 500, I think, in our demo. And in this example, we have the four properties of the model. That gets rendered as four columns. The width of the columns is set by the max width on the header cell that's defined in CSS. And you can either define the min and max width on the column itself in your component, or you can do it in CSS. And it will read from CSS and work out what its min and max is. If you define in both, it will take the most restrictive of the two. So I can grab the column header and move it around. There's a slight lag on it. There's actually a double render cycle in this version, which we're going to rewrite next week, which will speed up this side of it. And you can see here there's quite a long lag when it's going to Ember Collection. That's actually four render cycles, which again, we're going to do a rewrite of next week. And then this section here, the white section in the middle is all Ember Collection. So that scroll is in Ember Collection. And what we're doing is providing the eg grid row, which is that whole section across. And then the cells are within that component. So that's a very simple one. We've just got a header with the name of the field, capitalised, and the columns of data. And if I show you the template, oh, come on. I'm going to expand. The template is literally Ember Grid, data equals my data, columns equals name, age, comma salary, email. We're going to pull those keys out. So it's a one line declaration and you get yourself a table. It's fully stylable. If I inspect that, we have put very descriptive CSS names and everything. So we have here the header row inside that is a cell. So you can do header cell in your styling. And the only thing we are putting in inline CSS is the width. Everything else is in a CSS file so that you have complete control of styling. I've been having a few rants online about styling over the last few weeks. Ken and I have had a few goes back and forwards. I've been using components and found that because they've been defining a lot of their style inline, I can't override it. I can't bring it into line with my application style. So there's a few PRs waiting around of where I've taken that style out into CSS, which allows it to be overriding. The other thing you have to be very careful of is you're writing an add-on and you're writing into the inline style. You are forcing your app developer to allow CSP overrides of CSS self. And that has just opened up the whole cross-site scripting for their entire application. And I'll come on to that in a little bit as to how we solved it. Yes. No. Why would you need to? OK. No, you can't. Well, they are namespaced. So the root component is EmberGrid. So you can define EmberGrid header cell separately from anything else. Yes, but you could override them by creating a new namespace. But actually that's an advantage, isn't it? If you have a style for all your tables, if you drop this in and it uses pretty standard names of header cell body, then it's likely that a third party styling will just work here. OK. We can look at that, but I'd love a PR. So that's a very simple usage. It's a shame I can't show you the template and why that's not working. So if I look at the overview on this one, it's a lot more complicated. Use some of the overrides that are possible. So here we have the same data, but you'll see that the body cell here uses the row index. And then I want to make the data itself bold. I don't want the age column to be resizable, so it's not, but the name column is resizable. We've defined custom HTML for the salary header. And we've got an average salary at the bottom, which is a function in the controller or in component that contains this, that can then produce that average. So let's have a look at the code for that. So I'll start by showing you the minimal, where are we, tests dummy, these group and a while back. So these are our templates. I'm not quite sure why Sean's done it in this weird way, but the templates are actually defined in the JavaScript, which is strange. So the minimal one, that's the entire code for that minimal grid, that one line. So we're just saying here's our data. And we want these columns from that data in this order. And let's zoom that up for you. Is that any better? Can you read that? So if we take a look at the more detailed one here, we're saying first of all, the footer by default is invisible. So let's show the footer. We'll hook it up to our data. And our data is just an array of model objects. As of today, that can now be live array, or it can be a promise to an array. We set the row height. And we set the width and height of the grid itself. Now, if you don't set those, it will fill his parent. So you can do clever things with that. And then we define a column. So let's start with a simple column, the age column. So we have a key of age. That's the look up into the data. We have a width. That's the initial column width. If it was resizable, then you could resize it from that width. In this case, I'm saying resizable is false. So you can't resize this column, but default is true. And the alignment of the header footer and body is centered. So really simple. So setting up a simple grid of just 10 fields, you could do that by defining 10 columns. And you'd often running. So in this first one, we want to override the header. And so rather than just being the capitalized name of the field, we can supply a string for the header. We can also supply a string for the footer. We can put a min width and max width, or you can define those in CSS. And again, we've got alignment. In this case, in fact, there was a previous example where I can set the initial width to 350. But the max width is 300. It will actually apply the max width before rendering it. So you'll get a 300 width column in that case. Now, in this case, we want to override the body. You remember that in the body, sorry wrong one, that one, in the body, we want to have the row index and then the data in bold. So what we can do is bring in the eg body component. So this is a declarative body component. It's not the body itself. And that gives you the field, which is the data in the field, the row index and the column object. And on that column object, you can actually put your own arbitrary data. I can put Brian equals, as I'm sure I was dubbed earlier on by some other redheaded nutter. So within here, we just put the row index and then strong field, strong. So now we've got the row index followed by the data. And that will get re-rendered for every row by the grid. In the salary column, we want to be able to show the average in the footer. So rather than supplying a string as the footer, instead of supply a function, and that function will return the average salary. So you can provide anything you like there. And that function gets given the column object when it's called. So you can use that. You could use the same function for five different columns and do different things with them, for example. Here we want to override the header. So we can supply a header component and in this case, we've got a span just to override the styling and put a yellow color. And we get given the whole column object. So everything that's on this column is accessible to us. So in this case, column.header is a very long-winded way of just putting salary in there. And then the email is just a very simple column. That's about as simple as your columns can get. You don't even have to put a width. It'll just use the minimum max width as you've specified. So it gives you quite a lot of freedom. So if I can grab a chair as my legs are killing me, I'll take you through some of the code and show how this is achieved. So we have, we've done everything with pods, first of all, which has made, really cleaned up the code. It's the first time I've used pods and it's been very successful. So the column model is the piece in the middle that joins everything together. So when this is initialized, we said resizeable is true if it's not been set already. You can pass in a list of column objects when you create the grid. So you could pre-populate this the way that the adepar table works and do it in the controller if you want, or you can do it in the template. We set the default align to left and then we have this zones object. Now this is where the data for the header for footer and body is stored. Underscored because we don't really want the user grabbing hold of it, but you could if you want. And those are initialized to null. And then in the column component, we have a column associated with it. And if we're not given a column already, then we create one and give it a key of the element ID of this component. And then when we receive the attributes, we just go and push them onto the column. So all of the attributes on the EG column component end up being put on that internal model. And then when we render, it will go and pull up the parent view, which will be the grid, and it will push all of the columns, sorry, push this column onto the parent's list of columns. So now the grid has a list of all the columns that have been defined. So the column model is created by the column component, but it's stored on the grid. So once the grid starts up, it will render all the column components. They will render their internal components. And what that will do is populate the columns model array inside the grid. At that point, the grid now takes over rendering and creates its own components to actually render the content. So each of these components, actually its template, is completely empty. All it has to do is yield any block that's inside it. And the EG header, for example, just yields whatever's inside it. So if you've defined a block, it'll yield it out. Now what I'd love to be able to do is to not render the component at all to the DOM. But what we see in the DOM for this, if I inspect our DOM. So we have a declarative section, which we've said display none on, but if I get rid of that, you'll actually see it breaks all sorts of things. And inside there, those are our four column components. And then within those, there's the body definition component. And within that are the actual cells that are sitting waiting to be rendered on screen. So that you can see there where Ember Collection has gone and pre-built some of the rows that are off screen. And as that starts to scroll, you can see that it updates those. And they're being stored there ready to be shown later. So you can see there the render window. We've got rid of the 16 that were rendered initially. I don't know if I can actually zoom this view up. Okay. So this is within the body. You can see each of the rows here that's been rendered. And then those are being reparented into the grid itself when they're needed and being put back in here for storage when they're off screen. And because this whole section is hidden, we never see that on screen. So that magic is being done by the header component. What this does is when it receives its attributes, again we just stick them onto the header. And again we've got a header here. And that is injected into the parent view is the column, the eg column component. So that has an internal column. And then that has the zones object with a header object on it. And we just inject all of our attributes onto that header and stick it in. So now the column object, because we put an eg header component in, its header is now not null. It's got some data on it, which is what we supplied on that eg header component. And then once it's rendered, we then take our element, so our DOM element, and stick it into that same model. So we're injecting a DOM element into a data object, which is, as you said, crazy. But it works. And it works really nicely. And we can then pull that out later on. So the body footer and header just inject data onto that eg column model. They do nothing else. And we're actually splitting that functionality out into a new add-on called ember declarative, which is in alpha right now. But it deals with all the re-parenting and the fact that you've got one component to declare your data and another component to render it. So if you look out over the next couple of weeks, that will be fleshed out and we'll actually refactor this to use ember declarative rather than these direct implementations. We've then got an eg render section, which is all of the internals of the grid. So this is what's actually doing the work to show the content. So if we start with the header, here we've got a template that just says, for each column, put in an eg header cell, passing in that column into it. Dead simple. And all we have to do is bring in the class name bindings and we only deal with dragging here. Nothing else. The header cell then says, if no one's defined a header, then just put the default header in, which will use the alignment from the column and the text from the column. If it's resizable, then we'll also throw in a resize handle, which will allow dragging of the cells. So again, really, really simple. By dividing this into lots of small components, each individual component has been really easy to write. I think we wrote the alpha of this in about four to five hours, probably man hours. It's about three hours and two hours either side of the channel. We were surprised at how quickly we had something that actually worked. So in the header cell component, we bring down a header, which is just an alias from the column zone's header. So that's the data that was injected by the eg header component. And then we get a width and when that width is set, we constrain it using min and max width and reading from CSS to do that. And then when we set it, we set it on the column. So that means whenever you resize the header cell, the body and footer will be bound to that and will resize themselves simultaneously. We've then got some functionality bound dragging and then did render. So what this does is to, the after render here is needed on the first render because it's possible to be given a size that's outside the constraints. So this just forces it to be within the constraints. And then render header does the work. So what this does is to go and get the element from the header object. So that's the element that we injected earlier or the default from our template and will move that child from our source to our destination. So it's from the header element and just re-parent it into our element. So essentially we're now just a container for this other content. Now that sits after our template. So it'll inject it online 11 of our template essentially. So all this has to do is not do anything if the user has defined something to override it with. So if there is an element in the header, we just don't have to do anything. And we know there is because the header's been defined there. So that's basically it. The text just comes from a look up onto the column and it says if we've been given data then use it otherwise use the header that was defined or rather use the header that was defined otherwise use the capitalised look up. And then we have the resize handle which again trivially simple. It doesn't need to display anything. It's just a div. It's set to an absolute position so it's on the right hand end of the cell and it just overlaps the end of the cell. And the critical thing here is dealing with mouse move and capturing the document. So on a mouse down within the resize handle we set on the header which cell is being dragged and then start a mouse capture. And what that does is to hook the document mouse move mouse up mouse leave. And then when we end mouse capture we just have to unhook them. In fact I can see already that should be unhooked as well. I'm just going to do that. And then on mouse up we just set dragging header cell to null and end capture and on mouse move then we go and get the cell that we're moving. We get the offset of the cell and that tells us how far we've dragged this cell. I can set the new width and we set it on the cell. What that actually does in the cell is to set it on the column. So the cell applies its constraints and if you're within the constraints it will apply it to the column. So as you drag that cell around you're actually dragging the column which is dragging the head of the body and the footer all at once because they're bound to the column object. So the final piece of this is then doing CSP safe styling and I've built a new add-on for this. There was a lovely one called with style mixing which worked beautifully but isn't ember 2 compatible and making it ember 2 compatible was really hard. So I started from scratch. I've used the same concept and the same spec but rewritten it. So is everyone familiar with CSP and what it is? Anyone not? Okay so as a hacker you can inject JavaScript and other nasties into a page and what CSP does is within a header in your download of your HTML you're telling the browser where it is allowed to source JavaScript that it runs. So you can do this separately for images, data, JavaScript and styling. So you can list for example a list of domains that's allowed to receive data from but you can also say there is JavaScript embedded in my HTML so allow all JavaScript that's within the HTML. You can do the same with styling and you say I have inline styles so if there are inline styles you need to use them. Now as soon as you do that you are opening the if you're doing an add-on you're opening up the user's app to that not super injection JavaScript injection technique and it's not the add-on that would have to allow the CSP it's the whole application that would have to allow it. So if I take an example that has a width on it so a header cell has a width and what we've created is an add-on called CSP style mixing and the CLICSP style and you just add it as a mix-in and you define your style bindings and in this case we've got a width square brackets px which means take the result of the width property or function and inject the units px on the end if it's a number. If it's not a number then accept it. If it's a string if it's a safe string an HTML safe string then allow it straight through if not escape it. So this will deal with all of your internal styling safely. The other thing it will do is if we just injected it as a style attribute then you'd still need to enable CSP but if you use JavaScript to set the CSS the browser trusts your JavaScript because it's come from a trusted source. So you are allowed to modify the DOM and inject inline style whereas you can't do it through inline styles as text. So if you just set the style attribute it will break CSP but if you do it by setting it through code it won't. So this add-on does it through code and all I have to do is supply a width a computer property and whenever it changes the style binding will get applied and it will set that in JavaScript. If I look at a slightly more complicated one the body row I think is more complicated. So sorry no it's not it's the cell. There we go. So the cell has two style bindings it has a width and it has something slightly more complicated. So this one has a row height property which writes into the height CSS. Now you can also with this use the names gone question mark syntax and there's a name for it which is tertiary. That's what I'm looking for. If that's what you said. So I could write if row height returned a Boolean then you could write so you could do height 10 20. So if if row height returns true you'll get a height of 10 px and if it returns false you get a height of 20 px. So that's really nice and powerful. You can do all sorts of things with that. No it's function name followed by CSS name merely because it'll be true then false. Right? So if row height is true then you'll get 10 pixels always you get 20 pixels. So that's really important for this because I want to make sure it's a component that people can just use with confidence and you can drop it into any application. It's not going to break your application it's not going to cause you to have all sorts of security holes. So things that are coming in here there's more testing to be done. There's there's some pretty good testing but we're about halfway there with that. We want to be able to add sorting so header components that you can optionally drop in that will call into your containing component to ask you to sort the data and we want to handle scrolling columns as well as rows infinitely. So Sean's reason for writing this is he wants to write Excel in Ember with a million rows and a million columns and be able to scroll in both directions and there are some issues there with who controls the scroll bar because if you just put an Ember collection massively wide and you scroll it your scroll bar disappears off the right-hand edge very quickly. So we're looking at that sort of thing and if anyone else has any desires to help us take grouping expandable rows all sorts of different things that we might want to put in here bar charts components that we can drop in we would love to have your contributions because I think this could be a really powerful piece of the Ember framework that will work for anyone that wants to deal with data. It's styleable you can put any up any old data up to it and if we start to add those sort of more professional features to it it could become a big reason for people to move to Ember. Any questions? Is it possible to use things like cold span right now? No, no, but again one of the things that should be in there. The other thing is that all your rows have to be the same height because we have to be able to predict what row you're on when you scroll to a certain position. Is that the limitation of collection you're on? Yeah but that's well we're defining our own row so we could do cold span within the row. Is that the width there? Yes the height of every row has to be the same but again we could change that. That's the number of collections? Yes it is. Well it's more the Ember collection has a layout object as a strategy pattern and it's that layout object that says which of your rows are currently on screen. So if you do a knapsack layout with arbitrarily sized objects you could just lay them out all over the place and it will decide which 20 fit in your view. So that layout doesn't have that restriction you can put any old size objects into it. But the basic one that just does scrolling rows would have that restriction. Yes? From a practical point of view it seems to run very quickly just interested to know if it seems to sort of handle sort of large data sets. We've tested it with 100,000 rows and not seen any issues. I'd actually say it's quite slow at the moment. If I drag so if I go back to the this one so this has got however many thousand cells so this this has got 248 for some reason. But I've tried it with 10,000 and it's no different. The problem we've got at the moment is the fact that we're going through so many render cycles and there is the occasional bug like this one that it doesn't actually draw tall until you scroll back into the region that was pre-rendered. But then if you scroll slowly generally it's fine. Refresh! As I said, beta. Personal education question because I've moved from Brazil recently and I saw you were doing an import that I wasn't familiar with. Which one was that? I had an importing clearly braces and it seemed to give your access to a function which doesn't quite need it. So at the top you're imported but instead of just saying import such and such it was in a clearly brace. Yes, you can import what's essentially an object with several things in it. Right. Although I'm not expert on that either. Yes. Right. So you're importing part of the the... Yes. Are you familiar with the structuring? With what? The structuring? Not at all. I just I just do what I see in the guide. If you want to, if my advice for any ES6 so next feature is go on Babel. Go on Babel.js.io and use the try out feature. So have a look through the docs there and explain how each of these new things works and you can see and crucially you can see what ES5 code they turned into really directly. So it kind of demystifies them very nicely. The other thing that you might be particularly interested in we're using the new component integration test format and it's working really nicely except that helpers are not registered and I'd love to work with somebody to get helpers registered for integration tests without having to define that. So here for example what we're doing is it's not a good example as one that's got an inline template. So here's the example we want to check that there's a promise to an array being passed in and we want to check that when that promise resolves we get the new data. So we have a data promise which resolves to the internal data and what render template does is to do an hbs string of a template, renders it on the fly into a container and then we just expect elements within there. Now for some reason expect element works, expect component doesn't and when we raise this the response from the ember team is why the hell are you trying to expect component in a component test? Well because I've got nested components. So we're trying to get this one fixed at the moment I'm not quite sure where to go with this but we're working on it with various people. So what it will mean is that you can just render an arbitrary template there's no app defined at this point we haven't loaded the whole ecosystem so it's still a fast test but then we're just expecting that a certain number of in this case row DOM elements appear and we created about 10 tests around this in the space of an hour this afternoon with all the code required to do the promise based stuff and we found it to be really easy to write, very reliable and very quick. So I can recommend that new technique. Any other questions? We're looking that there's some work being done in ember table and the other part component for that to handle touch properly and we're looking to bring that across in our next phase of development but again anyone that wants to help with that we don't do a lot of mobile ourselves. We think it's just a case of bringing the touch and events across and handling them properly and it's probably worked to be done in ember collection rather than ember grid because we're delegating all of the the life-scrolling to ember collection. We felt this was better than trying to impose headers and footers onto ember collection we thought ember collection should just be an arbitrary layout of data but shouldn't have any borders and everything else around it and we think that's worked quite well but yeah I think ember collection is probably the best place to put that touch stuff and it would make more sense to go on now.