SmartView TriggerAction

Hello,

I’m trying to use a Smart View to display a list of Users with a specific template.

And I would like to trigger my SmartAction “Connect As User” that is available on my table User.
This smart action works fine with the classic table view on forest admin but not inside my smartview.

I followed the documentation that specifies this implementation to trigger an action inside the smartview:

{{button/beta-button
  type='primary'
  text='Reschedule appointment'
  action=(action 'triggerSmartAction' collection 'Reschedule' record)
}}

I replaced the example values with my values. This happens inside my for each loop where the record is displayed and accessible.

{{button/beta-button
                          type='primary'
                          text='Connect as user'
                          action=(action 'triggerSmartAction' collection 'Connect as user' record)
}}
<div class="c-smart-view">
  <div class="c-smart-view__content">
    <span class="c-smart-view_icon fa fa-{{@collection.iconOrDefault}} fa-5x"></span>
    <h1>
    </h1>
    <p>
      <h1>Liste de clients ({{@recordsCount}})</h1>
      {{collection}}

      <table style="width:100%">
          <tr>
            <th>ID</th>
            <th>Email</th>
            <th>Entreprise</th>
            <th>Actions</th>
          </tr>
            {{#each records as |record|}}
              <tr>
                <td class="tableCell">{{record.id}}</td>
                <td class="tableCell">{{record.forest-email}}</td>
                <td class="tableCelle">{{record.forest-companyName}}</td>
                <td class="tableCell">
                     {{button/beta-button
                          type='primary'
                          text='Connect as user'
                          action=(action 'triggerSmartAction' collection 'Connect as user' record)
                      }}
                </td>
              </tr>
            {{/each}}
        </table>

    </p>

    <button/beta-button {{action 'fetchRecords'}}>
        Refresh data
    </button>


  </div>
</div>
import Component from '@ember/component';
import { triggerSmartAction, deleteRecords, getCollectionId, loadExternalStyle, loadExternalJavascript } from 'client/utils/smart-view-utils';

export default class extends Component {
}

Expected behavior

The Action should be triggered

Actual behavior

When I press the button, the spinner is running.
The button seems to indicate that something is loading, but nothing happens

Context

Please provide any relevant information about your setup.

  • Package Version:
"dependencies": {
    "axios": "^0.21.0",
    "chalk": "~1.1.3",
    "cookie-parser": "1.4.4",
    "cors": "2.8.5",
    "debug": "~4.0.1",
    "dotenv": "~6.1.0",
    "express": "~4.16.3",
    "express-jwt": "5.3.1",
    "forest-express-sequelize": "6.7.6",
    "morgan": "1.9.1",
    "pg": "8.5.1",
    "require-all": "^3.0.0",
    "sequelize": "6.5"
  }

Hi @gaelperon,

Do you have any error in your browser console that could help us to debug your issue?

Hi, that’s what I have in my console when I click on the button

vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:5342 Uncaught TypeError: Cannot read property 'apply' of undefined
    at e.n._join (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:5342)
    at e.n.join (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:5308)
    at h (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3913)
    at vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:2093
    at a (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3831)
    at l.action (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:2093)
    at l.value (client-9af9d637e32be14106bd9957ba3dcd2f.js:4395)
    at l.trigger (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3599)
    at l.n [as trigger] (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3459)
    at e.n._run (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:5343)
    at e.n._join (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:5342)
    at e.n.join (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:5308)
    at h (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3913)
    at vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3613
    at a (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3831)
    at Object.handleEvent (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3613)
    at l.handleEvent (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3538)
    at HTMLButtonElement.<anonymous> (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:3563)
    at HTMLBodyElement.dispatch (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:1548)
    at HTMLBodyElement.g.handle (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:1543)
    at HTMLBodyElement.r (vendor-755b2587ddb911f7820d11d5b5f8c8f7.js:24480)

Do you have any update on the subject ?

Do you have on the live demo or elsewhere a simple example with a SmartView implementing a list and a smart action ?

All the examples of SmartViews on the live demo are good showcases, but in my opinion, they are way too complicated to understand how to implement SmartViews. I’m a bit lost :slight_smile:

Hi @gaelperon,

So first one little things is that we are using Ember 3.20, the syntax you use is pretty old but I guess it’s because it might come from the documentation. If you have the link we will update those outdated syntax :pray:, thanks in advance.

So you can replace:

{{button/beta-button
  type='primary'
  text='Connect as user'
  action=(action 'triggerSmartAction' collection 'Connect as user' record)
}}

by this

<Button::BetaButton
  @type="primary"
  @text="Connect as user"
  @action={{fn this.triggerSmartAction @collection 'Connect as user' record}}
/>

But of course that won’t fix your issue.
Your issue is coming from this file:

import Component from '@ember/component';
import { triggerSmartAction, deleteRecords, getCollectionId, loadExternalStyle, loadExternalJavascript } from 'client/utils/smart-view-utils';

export default class extends Component {
  // You deleted the important part here
  @action
  triggerSmartAction(...args) {
    return triggerSmartAction(this, ...args);
  }

  @action
  deleteRecords(...args) {
    return deleteRecords(this, ...args);
  }
}

Without this the triggerSmartAction would not be deefined and so you get the error you just had :wink:

1 Like

Hello @vince, thanks for the answer

You are right, my code comes directly from the official documentation here : Create and manage Smart Views - Documentation

And it comes also from the default code when you initialize a new SmartView.

Well, I tried your suggestion.
The template part is OK :ok_hand:

But when I replace the component part by your code, the records are not displayed anymore. :thinking:
The list is empty

I suppose records are not injected anymore because we didn’t override the fetch method ? But that’s only a supposition because I don’t know the content of the component we are extending.

1 Like

Here the screencast to explain : forestSmartViewComponent.mp4 - Google Drive

It’s because you have records in your template but it should be @records :wink:

Thanks. Now the records are displayed :ok_hand:

But the smart action is still not triggered

I tried with your code and also replacing collection by @collection

Do you have any error logs ?

Could you please reshare your new template and component :pray:

<div class="c-smart-view">
  <div class="c-smart-view__content">
    <span class="c-smart-view_icon fa fa-{{@collection.iconOrDefault}} fa-5x"></span>
    <h1>
    </h1>
    <p>
      <h1 class="title">Liste de clients ({{@recordsCount}})</h1>
      Current page : ({{@currentPage}})
      Number of pages : ({{@numberOfPages}})
      Collection : ({{@collection}})

      <table style="width:100%">
          <tr>
            <th>ID</th>
            <th>Email</th>
            <th>Company</th>
            <th>Actions</th>
          </tr>
            {{#each @records as |record|}}
              <tr>
                <td class="tableCell">{{record.id}}</td>
                <td class="tableCell">{{record.forest-email}}</td>
                <td class="tableCelle">{{record.forest-companyName}}</td>
                <td class="tableCell">
                     <Button::BetaButton
                        @type="primary"
                        @text="Connect as user"
                        @action={{fn this.triggerSmartAction @collection 'Connect as user' record}}
                      />
                </td>
              </tr>
            {{/each}}
        </table>
    
    </p>

    <button/beta-button {{action 'fetchRecords'}}>
        Refresh data
    </button>
    

  </div>
</div>
import Component from '@ember/component';
import { triggerSmartAction, deleteRecords, getCollectionId, loadExternalStyle, loadExternalJavascript } from 'client/utils/smart-view-utils';

export default class extends Component {
  @action
  triggerSmartAction(...args) {
    return triggerSmartAction(this, ...args);
  }

  @action
  deleteRecords(...args) {
    return deleteRecords(this, ...args);
  }
}

You have an issue here:

// This
    <button/beta-button {{action 'fetchRecords'}}>
        Refresh data
    </button>
// Should be
    <Button::BetaButton
      @type="primary"
      @action={{@fetchRecords}}
   >
        Refresh data
    </Button::BetaButton>

This I think should fix your issue :slight_smile:

Thanks, but the 2 buttons (triggerSmartAction and fetchRecord) do not work => a circular loader is displayed when clicked

You are missing an import:

import { action } from '@ember/object';

Thanks, it works with the import :slight_smile:

But I also had to remove this part to make it work

@action deleteRecords(...args) { return deleteRecords(this, ...args); }

Ok, just had to remove the second @action

Here is the final code of the component.

import Component from '@ember/component';
import { triggerSmartAction, deleteRecords, getCollectionId, loadExternalStyle, loadExternalJavascript } from 'client/utils/smart-view-utils';
import { action } from '@ember/object';

export default class extends Component {
  @action
  triggerSmartAction(...args) {
    return triggerSmartAction(this, ...args);
  }
  
  deleteRecords(...args) {
    return deleteRecords(this, ...args);
  }
}

But delete action is not working :expressionless:

I’m using this line to call the action (I found the example in the documentation) :

 <Button::BetaButton
                        @type="danger"
                        @text="Delete user"
                        @action={{fn this.deleteRecords record}}
                        @async={{false}}
                      />

Ref Doc :Create and manage Smart Views - Documentation

Error log :

User deletion failed: {"errors":[{"status":422,"detail":"`ids` must be a non-empty array."}]}

You can’t remove the @action on deleteRecords :wink:

If a add @action above deleteRecords, I have this error in the console

Uncaught (in promise) TypeError: Cannot set property deleteRecords of [object Object] which has only a getter