Closed johnraz closed 8 years ago
Hi, Yeah tables are a pain. One thing I don't understand. You have this template
var petLayout = function(locals) {
return (
<span>
<td>{locals.inputs.name}</td>
<td>{locals.inputs.type}</td>
</span>
);
};
but the model is
var Pet = t.struct({
type: Animal
});
What's locals.inputs.name
?
Hey @gcanti , Silly mistake on my side ;-)
I updated the initial issue's content
I removed name from Person
and moved it where it belongs:
var Pet = t.struct({
name: t.Str,
type: Animal
});
I was thinking maybe I could simply override the field template instead of the pet template ?
Does that sound as a viable option ?
I just can't find a workaround for React's limitation in returning only one node from a render
method :-(
var petLayout = function(locals) {
return (
<div> // <= ouch!
<td>{locals.inputs.name}</td>
<td>{locals.inputs.type}</td>
</div>
);
};
Yep, same here :/
So I guess I will have to deal with a field level template then. I'll let you know how it turn out
won't doing this work?
var petLayout = function(locals) {
return ([
<td>{locals.inputs.name}</td>,
<td>{locals.inputs.type}</td>
]);
};
@VinSpee sadly it will not work no, react still complains with Adjacent JSX elements must be wrapped in an enclosing tag
Hi @johnraz,
I know it's probably too late, but I found an interesting hack:
const Animal = t.enums({
dog: 'Dog',
cat: 'Cat'
})
const Pet = t.struct({
name: t.Str,
type: Animal
})
const Person = t.struct({
pets: t.list(Pet)
})
const listLayout = locals => {
return (
<table className="table table-bordered table-responsive table-striped">
<thead>
<tr>
<th>Pet name</th>
<th>Pet type</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{
locals.items.map((item) => {
//
// here's the trick: setting the template on the fly and clone the item!
//
const options = {
template: (sublocals) => {
return (
<tr key={item.key}>
<td>{sublocals.inputs.name}</td>
<td>{sublocals.inputs.type}</td>
<td>
{
item.buttons.map((button, i) => {
return <button key={i} className="btn btn-info" onClick={button.click}>{button.label}</button>
})
}
</td>
</tr>
)
}
}
return React.cloneElement(item.input, {
key: item.key,
options: options
})
})
}
<tr>
<td colSpan="3">
<button className="btn btn-info" onClick={locals.add.click}>{locals.add.label}</button>
</td>
</tr>
</tbody>
</table>
)
}
const options = {
fields: {
pets: {
template: listLayout
}
}
}
It's somehow horrible, but seems to work. Probably it's too risky for production code though
Hi,
I'm trying to achieve the following look and feel for my list:
After following the guidance here #109, I ended up with the template shown at the bottom of this issue.
The problem with that template is that the
petLayout
is breaking the dom (because the
<div>
is a child of a<tr>
) and hence react raises anInvariant Violation
error due to the dom being auto-corrected by the browser (tried in chrome).Using a
<tr>
tag instead of the<div>
breaks too.I've been able to go around this with the following:
It kinda does work "by chance" because the way the browser is auto-correcting the dom suits react ... But it is very fragile and I'd like to find another way.
I could ditch the
<table>
and try to recreate the same design with divs but well, the rest of the application is using tables for such components and I'd like to keep it simple.Thanks again for the support !