VulcanJS / Vulcan-Starter

VulcanJS starter repo. Use as a base for your own VulcanJS projects.
MIT License
127 stars 88 forks source link

ResolveAs doesn't work to appear the correct field on card #178

Closed Kellokes closed 4 years ago

Kellokes commented 4 years ago

Hi Guys,

I'm trying to get the name field of Service Schema and Field schema trough the Form Schema using Resolve As, but when I pass the fields of ServiceId and FieldsId in the field parameters on the ComponentCard dind't appear the result with name fields of Service Schema and Field Schema.

I believe that ResolveAs it is not ready correctly with the component card.

What are the correct settings that I need to make when I need to obtain a specific field of a relationship between two collections?

Check my schema.js and FormsList.jsx

schema.js of Forms `const schema = { // default properties

_id: {
  type: String,
  optional: true,
  canRead: ['guests'],
},
createdAt: {
  type: Date,
  optional: true,
  canRead: ['admins'],
  onCreate: () => {
    return new Date();
  },
},
userId: {
  type: String,
  optional: true,
  canRead: ['admins'],
  resolveAs: {
    fieldName: 'user',
    type: 'User',
    relation: 'hasOne',
  },
},

// custom properties

serviceId: {
  label: 'Service',
  type: String,
  optional: false,
  canRead: ['members'],
  canUpdate: ['admins'],
  canCreate: ['admins'],
  query: `
    query ServiceQuery {
      services{
        results{
          _id
          name
        }
      }
    }
  `,
  options: props =>
    props.data &&
    props.data.services &&
    props.data.services.results.map(service => ({
      value: service._id,
      label: service.name,
    })),
  input: 'select',
  resolveAs: {
    fieldName: 'service',
    type: 'Service',
  },
},

fieldsId: {
  label: 'Fields',
  type: Array,
  optional: false,
  input: 'checkboxgroup',
  query: `
      query FieldQuery {
        fields (input : { sort : { order : asc} }) {
          results{
            _id
            name
          }
        }
      }
    `,
  options: props =>
    props.data &&
    props.data.fields &&
    props.data.fields.results.map(field => ({
      value: field._id,
      label: field.name,
    })),
  resolveAs: {
    fieldName: 'fields',
    type: '[Field]',
  },
  canRead: ['members'],
  canCreate: ['admins'],
  canUpdate: ['admins'],

},
'fieldsId.$': {
  type: String,
  optional: false,
},

};

export default schema;`

FormsList.jsx `import React from 'react'; import { Helmet } from 'react-helmet'; import { Components, withMulti, withCurrentUser, registerComponent } from 'meteor/vulcan:core'; import Users from 'meteor/vulcan:users';

import Forms from '../../modules/forms/collection.js';

const FormsList = ({ results = [], currentUser, loading, loadMore, count, totalCount }) => ( <div style={{ maxWidth: '500px', margin: '20px auto' }}>

<Helmet>
  <link
    name="bootstrap"
    rel="stylesheet"
    type="text/css"
    href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css"
  />
</Helmet>

<div
  style={{
    padding: '20px 0',
    marginBottom: '20px',
    borderBottom: '1px solid #ccc',
  }}
>
  <Components.AccountsLoginForm />
</div>

{loading ? (
  <Components.Loading />
) : (
  <div className="forms">

    {Users.canCreate({ collection: Forms, user: currentUser }) ? (
      <div
        style={{
          marginBottom: '20px',
          paddingBottom: '20px',
          borderBottom: '1px solid #ccc',
        }}
      >
        <h4>Create New Document</h4>
        <Components.SmartForm collection={Forms} />
      </div>
    ) : null}

    {results.map(form => (
      <Components.Card
        fields={['serviceId', 'fieldsId']}
        key={form._id}
        collection={Forms}
        document={form}
        currentUser={currentUser}
      />
    ))}

    {totalCount > results.length ? (
      <a
        href="#"
        onClick={e => {
          e.preventDefault();
          loadMore();
        }}
      >
        Load More ({count}/{totalCount})
      </a>
    ) : (
      <p>No more items.</p>
    )}
  </div>
)}

);

const options = { collection: Forms, limit: 5, };

registerComponent({ name: 'FormsList', component: FormsList, hocs: [withCurrentUser, [withMulti, options]] });

`

ErikDakoda commented 4 years ago

Have you tried the new "Relations" api? https://docs.vulcanjs.org/relations.html

You should be able to drop query and instead add relation: 'hasOne' or relation: 'hasMany' to resolveAs

Kellokes commented 4 years ago

Hi Erik,

I dropped the query and added the relation to resolvAs, but it didn't work, this error appears for me:

TypeError: Cannot read the 'name' property of undefined

I tried with fieldName: 'name' and 'field' ... This parameter is the field name of my relation collection that I want to show in the front-end, correct?

fieldsId: 
      label: 'Fields',
      type: Array,
      optional: false,
      input: 'checkboxgroup',
      resolveAs: {
        fieldName: 'name',
        type: '[Field]',
        relation: 'hasMany'
      },
      canRead: ['members'],
      canCreate: ['admins'],
      canUpdate: ['admins'],

    },
    'fieldsId.$': {
      type: String,
      optional: false,
      canRead: ['members'],
    },
Kellokes commented 4 years ago

I resolved the problem, I forgot to define a fragments for each collection and configure them in my Datatable Component.

** The Card Component don't have a fragment option.