将多个列表视图添加到同一资源 - Admin-On-Rest

时间:2017-05-23 14:45:46

标签: admin-on-rest

我有一个故事资源,我想以不同的方式为同一个用户显示,具体取决于故事状态

status = NEW的故事应该与List1

一起显示

状态= APPROVED等的故事需要显示为List2(我需要显示故事的不同属性)

如何使用Admin-On-Rest实现此目的?

On添加相同的资源两次(如下所示)并为两者分配不同的列表视图只会导致第一个被显示而第二个被忽略

<Resource name="tales" list={EditorAssignedList} edit={EditTale} options={{ label: 'Assigned Tales' }}/>
<Resource name="tales" list={EditorTaleTrack} options={{ label: 'Your Tales' }}/>

记录以下错误。

flattenChildren(...): Encountered two children with the same key, `1:$tales`. Child keys must be unique;

有关如何将唯一密钥注入资源的任何策略。

3 个答案:

答案 0 :(得分:2)

如果您还希望将CRUD功能添加到同一路线但通过不同的列表菜单,则上述答案并不是很有用。如果您有2个列表视图List1和List2与CRUD组件。从List2输入编辑(例如)并点击保存,您将重定向到List1

更广泛的解决方案是为REST客户端创建自定义包装器。 来自下方的灵感。 https://marmelab.com/admin-on-rest/RestClients.html#decorating-your-rest-client-example-of-file-upload

对于我的情况,它看起来像这样。

我在App.js中创建了一个虚拟资源'trackTale'。在restWrapper.js中

const RESTWrapper = requestHandler => (type, resource, params) => {

      if (type === 'GET_LIST' && resource === 'trackTale') {
        const page =  params.pagination.page
        const perPage = params.pagination.perPage
        const {field, order} = params.sort
        const query = {}
        query['where'] = {...params.filter}
        if (field) {query['order'] = [field + ' ' + order]}
        if (perPage > 0) {
            query['limit'] = perPage;
            if (page >= 0) {
                query['skip'] = (page - 1) * perPage
            }
        }
        //Key part here hardcoding the tales route to trackTale

const url = config.host + '/' + 'tales?' +  queryParameters({filter: JSON.stringify(query)})
        const options = {};
        options.user = {authenticated: true}
        options.user.token = localStorage.getItem('token');
        options.method = 'GET';
        return fetchUtils.fetchJson(url, options)
          .then((response) => {
            const {headers, json} = response;
            //admin on rest needs the {data} key
            return {data: json,
                    total: parseInt(headers.get('x-total-count').split('/').pop(), 10)}
        })
    }
}


//below function is very very specific to how loopback.js expects to recieve REST queries. Please customize it for your API needs
const queryParameters = data => Object.keys(data)
    .map(key => [key, data[key]].map(encodeURIComponent).join('='))
    .join('&');

这适用于所有情况。如果您的不同路线没有CRUD,仍然可以创建自定义菜单。

答案 1 :(得分:1)

只保留一个资源。创建一个包含2个条目的自定义菜单,将您的过滤器传递给url参数。

然后在TalesList组件中,根据您的参数显示正确的版本组件

答案 2 :(得分:0)

@Gildas提供了很棒的惊人帮助

这是通过

解决的

1)创建自定义菜单组件

const linkData = {
  pathname: "/tales",
  hash: "trackTales"
}

export default ({ resources, onMenuTap, logout }) => {
  return (
    <div>
      <MenuItem containerElement={<Link to="/tales" />} primaryText="Tales For Edit" onTouchTap={onMenuTap} />
      <MenuItem containerElement={<Link to={ linkData } />} primaryText="Track Tales" onTouchTap={onMenuTap} />
      {logout}
    </div>
  )
}

React Router的Link Component接受对象作为参数。这些作为道具传递给下游组件。

export const EditorAssignedList = (props) => {
  return taleViewJuggler(props)
}

juggler函数读取道具并根据道具创建自定义视图。链接组件将数据传递到道具中的“位置”键。

const taleViewJuggler = (props) => {
  let viewName = props.location.hash
  let component;
  switch (viewName) {
    case "case1":
      component = (
        <ListView1 />
      )
      break;
    case "#case2":
      component = ( < ListView2 /> )
      break;
  }
  return component
}