CRUD list of cars, with a possibility to assign car categories

Hey fellow developers,

I am going to build a CRUD list of cars with React and Meteor, and I have one question I can’t answer for sure.
I mean, I am not sure what is the “right way” of doing it.

So…

I want to create a form, and make it possible to add new cars by filling in the form fields. However each car should be assigned to a category / group so I can filter them later with those groups. Those groups will be displayed as a dropdown inside Add a Car form.

I plan to make possible to CRUD those groups as well :slight_smile: Should I define a new schema for them or should I do that inside of cars schema?

Unless you want to search all your cars collection for categories you’ve used, you should put them in a separate collection. Furthermore, if you want to be able to add descriptions or add the category labels, you should put the id’s of the category in your Cars.categories array. Downside with this approach is that you need to lookup the category data when you display the car/cars list, plus that you will have problems doing a simple, one collection, search that includes categories.

There’s no “best” solution here, as I see it.

What kind of schema are we talking, SimpleSchema?

@copleykj @ralof ell… I think I will go with Simple Schema (would you suggest something else?). I am kinda making decisions on the fly here, not super familiar with meteor world.

In simple schema I can introduce something like options right?

options: { option1: "Some content", option2: "Some other content" }

Is there a way to modify them? Or if something is schema it is fixed, rock solid.

Schema is fixed, so if you use aldeed’s autoform, schema and collection2 you could have something like this:

Categories = Collections.Categories = new Mongo.Collection('categories');
Cars = Collections.Cars = new Mongo.Collection('cars');

Schemas.Category = new SimpleSchema({
   label: {
     type String
   },
  description: {
    type String
  }
})

Schemas.Car = new SimpleSchema({
   make: {
     type String
   },
  model: {
    type String
  },
  categories: {
    type: Array
  },
  'categories.$': {
    type: String,
     type: "select",
            options: function(){
                return dropDownOptionsForCategories();
            },
    }
})

//connect the schema
Categories.attachSchema(Schemas.Category);
Cars.attachSchema(Schemas.Car);

In client startup:

 dropDownOptionsForCategories = function(){
   var options = [];
   Categories.find().forEach(function(cat){
     options.push({label: cat.label, value: cat.label});
  }
 return options;
} 

@ralof thanks a lot! It will definitely help. One quick question to the schema. I want to use isActive boolean and toggle it with switches:

should I add false / true as options as well ?

@ralof any docs / articles worth reading in the subject? I find Meteor tutorials quiet shallow, and while googling stuff I mostly encounter 2015 / 2016 articles, that are partially outdated.

On the other hand I have some youtube videos like lvlUpTuts, but they are usually outdated too. :frowning:

In terms of aldeed repos, I should use the following 3 ?



Yes, those are great but I see now that you use React, I don’t know how/if they work with that. I’ve always used Blaze

Well, when I figure it out how to connect the dots, I will let you know :smiley:
Thanks again for the willingnes to share your knowledge. Much appreciate it.

1 Like

I wish I had better availability yesterday to give you proper information on this… Better late than never though I guess :slight_smile:

Basically what you want to do here is use the allowedValues rule on the schema key and set it to a function that returns the list of categories from where ever you choose to store it. I’m guessing being that you want to CRUD the categories, that will be in the DB, so I find and map should do the trick.

const CarsSchema = new SimpleSchema({
    categories: {
        type: Array,
    },
    'categories.$': {
        type: String,
        allowedValues: () => CategoresCollection.find().map((category) => category.name);
    },
});

There are some optimizations that could be applied like caching the categories to an array, using a cursor observer to change the array when the categories change in the DB, and then just returning that array from your allowedValues function.

There are of course caveats as well that you’ll need to anticipate for things to function properly. Namely the fact that for this to work, the categories will need to be published to the client or autoform’s validation will fail. This is a pretty good use case for a null publication, and the cursor observer optimization could be set up on the client as well…

Also, Autoform should use the allowedValues to populate the dropdown automatically.

Hopefully this helps.

2 Likes

Updated my code sample to reflect proper structure of the schema since categories is of type Array

If you are using React I would suggest you use Uniforms for form generation. Works with simple schema and Material-UI out of the box. Also, well maintained with responsive developer support.

Does it work with material-ui-next or just material-ui? I am using next, so that’s quiet important for me.

Currently uniforms-material has a peer dependency set as "material-ui": ">=0.16.7 <1.0.0", This doesn’t mean it won’t work though as there may be minimal changes to the components that Uniforms uses. My personal recommendation is to give it a try, peer dependency warnings be damned™, and see what happens. If you find issues maybe you can fix them and submit a PR.

Looks like there is already a pull request to support MUI v1.0. You should comment on this PR to get a status. Sounds like they are waiting to fix and merge this PR when MUI officially goes 1.0.

2 Likes

Thanks, I have pinged them, we will see what they will reply

I already tried the mix of those two (next and 0.2) for React components only, it’s piece of cake with yarn, however it adds the extra bloat to my code I really don’t like. Especially with react you need to always check the import pathtwice to recall the component origin, cause they have simillar names, and I found it preety anoying after while.

Not mentioning few glitches I have to come around. In my opinion it’s unprofitable tradeoff