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

Sub-collections #153

Closed
azproduction opened this issue Feb 3, 2014 · 72 comments
Closed

Sub-collections #153

azproduction opened this issue Feb 3, 2014 · 72 comments

Comments

@azproduction
Copy link

Hello!

I have complex model with nested collections. I'm trying to define such model

{
    title: { type: String, required: true },
    images: {
        type: [{
            name: String,
            image: Types.Url,
            thumb: Types.Url,
            description: String
        }]
    }
}

And I get an error Error: Fields must be specified with a type function @ keystone/lib/list.js:298:9.

Is it possible to define that collection in keystone? (it is possible in Mongoose)

In admin UI this field should look like list of items with Add, Edit and "Trash" buttons. Add and Edit buttons should open modal dialog.

I am new to keystone, but I want to contribute to this project. And it will be great if you guide me a bit.

@JedWatson
Copy link
Member

Hello!

Complex models with nested collections (or, for that matter, using mongoose's Mixed Schema Type) are currently (a) possible, and (b) not supported in the Admin UI yet.

The mongoose schema is available for you to modify to your heart's content, so you could still achieve the schema you want like this (assuming your schema snippet is for a gallery):

var Gallery = new keystone.List();
Gallery.add({
    title: { type: String, required: true }
});
Gallery.schema.add({
    images: {
        type: [{
            name: String,
            image: String,
            thumb: String,
            description: String
        }]
    }
});
Gallery.register();

The downside is, obviously, the images field will be completely ignored by the Admin UI, and you won't get those Add, Edit and Trash buttons :)

I'd really like to add this capability in the future (or perhaps support proper nested Lists, in the same way mongoose supports nested Schemas), but haven't had a chance to actually look into doing it yet.

In theory, it actually shouldn't be too hard to do, although when implementing it I'd want to put some work into the UI and make it really good. I'm not sure about using modal dialogs (it might be better UX to just render the forms inline) and there are some cases where it would need to be more intelligent (e.g. how should the UI adapt when you have 100+ items in the array? etc.)

Have mentioned this a few times now in different issues, but moving to a client-side rendering system for the Admin UI would make things like this easier to implement. At the moment the client-side of the Admin UI is very basic, so that might be something to do before adding this functionality.

That said if you're up for contributing support for this as a feature, I'd be happy to work with you on it!

@JedWatson
Copy link
Member

@floatdrop that's not what's causing the error in this case, Keystone maps the basic Javascript data types to field types.

For reference, the defaults are:

  • String = Types.Text
  • Number = Types.Number
  • Boolean = Types.Boolean
  • Date = Types.Datetime

This was done in part to make schema transition from Mongoose to Keystone easier, and is throughout the demo / sample code. Might be a good idea to encourage people to be explicit instead...

@jergason
Copy link

Any pointers on getting started in creating an admin UI for nested objects? Where should I begin my explorations in the code?

@JedWatson
Copy link
Member

Good question, @jergason. You got me thinking.

I suspect it'll be a new Field Type, that creates its own Schema. Probably best we work out the API on how to define nested fields first, then it might be clearer.

As a start, it could go like this (to use the Gallery example above):

Gallery.add({
    title: { type: Types.Text, required: true },
    images: { type: Types.Nested, fields: {
        name: String,
        image: Types.CloudinaryImage,
        description: Types.Markdown
    }}
});

The Nested field type would create and manage its own Mongoose Schema object, and its addToSchema method would look something like this:

Nested.prototype.addToSchema = function() {
    this.list.schema.path(this.path, [this.schema]);
}

It would also have its own fields array (like the List class does).

You could extend the nested Schema with virtuals / methods / etc like this (before calling List.register())

Gallery.fields.images.schema.methods.something = function() {}

You could also add more fields to its schema after it was added, like this:

Gallery.fields.images.add({
    copyright: String
});

The next step would be to work out how we would work with nested schemas in the UpdateHandler, and finally a somewhat fancy form field template for it.

Let me know what you think. If you like, I'll create a branch where we can work on it together.

@jergason
Copy link

That sounds excellent. Next week I might have some time to work on this full-time, since we are looking at using Keystone as an admin interface for some of our mongo data.—
Sent from Mailbox for iPhone

On Wed, Feb 12, 2014 at 5:00 AM, Jed Watson notifications@github.com
wrote:

Good question, @jergason. You got me thinking.
I suspect it'll be a new Field Type, that creates its own Schema. Probably best we work out the API on how to define nested fields first, then it might be clearer.
As a start, it could go like this (to use the Gallery example above):

Gallery.add({
    title: { type: Types.Text, required: true },
    images: { type: Types.Nested, fields: {
        name: String,
        image: Types.CloudinaryImage,
        description: Types.Markdown
    }}
});

The Nested field type would create and manage its own Mongoose Schema object, and its addToSchema method would look something like this:

Nested.prototype.addToSchema = function() {
  this.list.schema.path(this.path, [this.schema]);
}

It would also have its own fields array (like the List class does).
You could extend the nested Schema with virtuals / methods / etc like this (before calling List.register())

Gallery.fields.images.schema.methods.something = function() {}

You could also add more fields to its schema after it was added, like this:

Gallery.fields.images.add({
    copyright: String
});

The next step would be to work out how we would work with nested schemas in the UpdateHandler, and finally a somewhat fancy form field template for it.

Let me know what you think. If you like, I'll create a branch where we can work on it together.

Reply to this email directly or view it on GitHub:
#153 (comment)

@JedWatson
Copy link
Member

@jergason how's it looking for working on this this week? if it's looking good, I'll do some prep work to get it ready :)

@jergason
Copy link

I can work on this from tomorrow through the end of the week. I'm in the
US, so that is about 18 hours from now.

I'll try to read through the code a bit to prep for it.

On Sun, Feb 16, 2014 at 11:35 PM, Jed Watson notifications@github.comwrote:

@jergason https://github.com/jergason how's it looking for working on
this this week? if it's looking good, I'll do some prep work to get it
ready :)

Reply to this email directly or view it on GitHubhttps://github.com//issues/153#issuecomment-35231919
.

@mdciotti
Copy link

mdciotti commented Apr 8, 2014

@jergason any updates on this feature?

@subhog
Copy link

subhog commented Apr 16, 2014

Question: I want to have the following schema:

Blog.add({
  admins: [{
    user: {type: Types.Relationship, ref: 'User', index: true},
    role: {type: Types.Select, options: 'editor, moderator},
  }],
});

When I try this directly, I got the same error: Error: Fields must be specified with a type function. However, when I do this via Mongoose schema with Blog.schema.add, I got:

TypeError: Undefined type at `user`
Did you try nesting Schemas? You can only nest using refs or arrays.

How can I achieve the schema I need?

@JedWatson
Copy link
Member

@subhog You can't use Keystone field types in nested schemas until this feature is ready. At the moment, the best way to achieve what you're after (if you want the admins for each blog manageable in Keystone) is to create a new list called BlogAdmins and link it to both Blog and User models.

The management workflow isn't going to be ideal though, we should really get around to getting this feature done.

@jergason are you still interested in working on this?

@subhog
Copy link

subhog commented Apr 17, 2014

I've started the implementation.

@subhog
Copy link

subhog commented Apr 18, 2014

For anyone interested.

I've made a version that accepts the subcolleciton schema and seem to work fine for basic needs. Which is actually surprising, as I needed to pull one dirty trick that doesn't seem like a proper way to solve this problem.

That fork is available here and you can use it in apps by changing dependency path in package.json to "keystone": "subhog/keystone#array-field". Collaboration is welcome.

Api

field: [{
  subfield: {...},
  ...
}],

Or:

field: { type: Array, schema: {
  subfield: {...},
  ...
}},

Or:

field: { type: Types.Array, schema: {
  subfield: {...},
  ...
}},

Notes

  • I need to verify whether saving actually works.
  • To loop through the data you must use model.field.toObject() instead of just model.field.
  • UI is very basic and read-only, just to display something and not crash the app.
  • There might be problems if array schema has a nested object.
  • I didn't even touch the problem of integration with app updates.

@salzhrani
Copy link

Maybe submit a PR and @JedWatson could critique it and and possibly merge it

@subhog subhog mentioned this issue Apr 26, 2014
@subhog
Copy link

subhog commented Apr 28, 2014

PR sent. @JedWatson, suggestions?

@JedWatson
Copy link
Member

@subhog sorry for the delay, it's a pretty big PR. I'm reviewing it and will get back to you with feedback soon.

@jefersonsv
Copy link

Hello,

I'm using admin ui of keystone in commercial application. therefore, this PR is very important, I'm watching to know when this will be resolved.! Thanks for all.

@mavropalias
Copy link

I've stumbled upon the same issue, as I need nested collections in my project. I'll keep hitting F5 on this page :)

@mattdesl
Copy link

👍 this would be great!

@zordon
Copy link

zordon commented Aug 28, 2014

Hey, I think I'm gonna help, I just made a small dive in the field libs. I have one question, to get this done, basically you need to make a lib and template for that type of field?

dkhurshudian added a commit to dkhurshudian/keystone that referenced this issue Oct 29, 2014
dkhurshudian added a commit to dkhurshudian/keystone that referenced this issue Oct 29, 2014
@dkhurshudian
Copy link

I'm working on this feature, and have done something...

@joelbowen
Copy link

Any updates? Or is there any common case solution for something like creating menus as a list?

I'm trying to create a keystone list of menus I can then output for things like primary navigation and footer navigation. My Schema would look something like:

title: { type: String, required: true },
links: {
    type: [{
        label: String,
        href: Types.Url,
        key: String
    }]
}

Just a thought, in general this functionality would have huge benefits (if still editable in the admin UI).

@kapandaw
Copy link

@JedWatson Do you have any progress in 'sub-collections' question?
Thanks.

@BerkeleyTrue
Copy link
Contributor

I don't think there has been an progress on this as the admin is being completely rewritten using React and Keystone itself using Express 4. This is slotted to finish early January. Don't think anyone is going to be able to get around to it till then. If someone would like to try to tackle this and submit a PR using the new admin, that would be great!

@morenoh149
Copy link
Contributor

@mandb 👍 I saw that as well. Haven't used it yet though.

@mandb
Copy link

mandb commented Nov 9, 2015

Doesn't work on sharded collections and can only work with exact matching
fields, but it's a good step and can give exactly this functionality.
On Nov 8, 2015 7:59 PM, "Harry Moreno" notifications@github.com wrote:

@mandb https://github.com/mandb [image: 👍] I saw that as well.
Haven't used it yet though.


Reply to this email directly or view it on GitHub
keystonejs/keystone#153 (comment)
.

@CubicflowDan
Copy link

+10 This is the only thing preventing me from using keystone in a number of production websites/apps.

@simonwidjaja
Copy link

Any news on this?

@jogonru
Copy link

jogonru commented Jan 18, 2016

+1

@wmertens
Copy link
Contributor

@Bockit Did you get it to save?
@JedWatson without saving there is no workaround for this 😢.

If this gets implemented, does that mean that the current conversion of nested objects into flat fields will become objects again? If so, that's a breaking change of course, if not, how to do it?

Note that with React, making nested editors for nested objects is easy, simply recurse editors in the rendering function.

@sachss
Copy link

sachss commented Feb 16, 2016

I'd suggest anyone interested in this see and support #2265.

@Bockit
Copy link

Bockit commented Feb 16, 2016

@wmertens I did, the code is at home, I'll try and dig it up. IIRC I was misunderstanding something about how the feature worked.

@VinayaSathyanarayana
Copy link

Any updates on this? Will this be part of V0.4?

@jjhesk
Copy link

jjhesk commented Apr 16, 2016

if i need to use cloudinary in the api just to insert the info as the object. How can i use the cloudinary schema object as the new insert object? any sample code?

@jbpin
Copy link

jbpin commented Jul 6, 2016

I admit it will be really pleasant to have an ObjectArray type instead of using relations. +1

@wmertens
Copy link
Contributor

Arrays of Objects are being worked on, they are already working in fact :)

See keystonejs/keystone#3300 and keystonejs/keystone#3282 for progress.

I hope that we can replace all the Array types with them (in a backwards compatible way). Then we can implement reordering too.

@simonwidjaja
Copy link

+1 I would be interested in an update as well...

@ghuroo
Copy link

ghuroo commented Mar 8, 2017

Any chance of seeing this in a 4.0.6 beta?
Or can we implement sub-collections trusting that this feature will be out someday soon?

@Adrian-Kardasz
Copy link

Yeah this is such a critical thing for me so that the web app admins can edit data easily (they're not to savy)

@mrth2
Copy link

mrth2 commented Nov 11, 2017

yah, this should be done for the extendable admin 👍
any update @JedWatson ?

@semeano
Copy link

semeano commented Jan 8, 2018

This would be so awesome!

@onedevlad
Copy link

Hey, @JedWatson, are there any updates on this one?

@semeano
Copy link

semeano commented Mar 26, 2018

I've ended up creating a new type called List that allows that. You can check my fork of keystone.

images: { type: Types.List, required: true, initial: true, default: [],
	fields: {
		title: { type: Types.Text, required: false, initial: true },
		alt: { type: Types.Text, required: false, initial: true },
		url: { type: Types.Text, required: true, initial: true }
	}
}

@dejavu1987
Copy link

+1

@ohadperry
Copy link

+10

@leouz
Copy link

leouz commented May 15, 2019

+1

@gautamsi
Copy link
Member

gautamsi commented Jun 2, 2019

unfortunately nested lists are dropped from keystone 4, see #3282, Keystone 5 promises to pick it up. see keystonejs/keystone-5#195

closing this for tidiness.

@gautamsi gautamsi closed this as completed Jun 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests