Is it possible to import files for Smart Views?

Wondering if it’s possible to include any files when working with Smart Views. I have several Smart Views with duplicate code that I’d love to be able to reduce and instead pull in a util file for these cases. Is it possible?

Hi @David_Panzarella,

Well there is no documented way to do it, but if your files are on your side you could do something like that maybe:

export default class MyComponent extends Component {
  @service lianaServerFetch;
  // This is a private service
  @service smartCodeRegister;

  async loadMyOwnComponents(componentName) {
    const response = await this.lianaServerFetch(`/components/${componentName}`);
    const componentData = await response.json();
    
    // Style, template and component must be STRING
    await this.smartCodeRegister.registerStyle(componentName, componentData.style);
    await this.smartCodeRegister.registerTemplate(componentName, componentData.template);
    await this.smartCodeRegister.registerComponent(componentName, componentData.component);
  }
}

Thanks, @vince! I had no idea this was an actual thing!

For clarity here, this looks like this replaces any number of files needed hard-coded into each view: I assume you can register any or all for style, template, and component? Furthermore, would this only inject whatever component into each or would it completely replace them?

Ex: in my case, if I just wanted to import a utility component using this.smartCodeRegister.registerComponent(componentName, componentData.component);, and then use its available methods further down in the component, would that be possible? Or is it more like a complete replacement of the overall component?

Let me know if I get it right, you want an abstract class to be used in multiple place, am I right ?

Not exactly. What I’d like is a utility component that pulls in different methods just like if I were to say import Moment and use its methods throughout my smart view component. What I’d like to do is use the same constants or other utility files that have helper methods and such, like I’m using in my forest and route files, in my smart views as well. This way I could pull in those same constants and methods into my smart views, thus reducing the amount of duplicated code.

On a different note, it’d be great to have a way for Forest to automatically check a folder path (just like it does now for routes, models, etc) for our smart views, but I’ve been told this isn’t an option just yet. I wish it were because trying to either code directly in the smart view editors or having to copy/paste from a local editor is tedious at best. Version control and backup of said code is an obvious factor as well. If you have better strategies around this I’d love to hear them.

Thanks again for the help!

So for loading external javascript file you can simply use the ``

import { loadExternalStyle, loadExternalJavascript } from 'client/utils/smart-view-utils';

export default class MyComponent extends Component {
  constructor(...args) {
    super(...args);

    this.loadUtilities();
  }

  async loadUtilities() {
    await loadExternalJavascript('https://my-environment-name.fr/my/utility/file.js');
  }
}

With the first code I gave you I think you can find a way to make it work. You’ll have to do a little bit aof code but not that much I think.

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';

export default class WrapComponent extends Component {
  @service lianaServerFetch;
  // This is a private service
  @service smartCodeRegister;

  @tracked componentName;

  constructor(...args) {
    super(...args);

    this.loadMyOwnComponents('NameOfYourComponent');
  }

  async loadMyOwnComponents(componentName) {
    const response = await this.lianaServerFetch(`/components/${componentName}`);
    const componentData = await response.json();
    
    // Style, template and component must be STRING
    await this.smartCodeRegister.registerStyle(componentName, componentData.style);
    await this.smartCodeRegister.registerTemplate(componentName, componentData.template);
    await this.smartCodeRegister.registerComponent(componentName, componentData.component);

    this.componentName = componentName;
  }
}

And in your hbs:

{{#if this.componentName}}
  {{#let (component this.componentName) as |MyComponent|}}
    <MyComponent
      @myArgument="something"
      @anotherArgument="Else"
      class="my-css-class"
    />
  {{/let}}
{{/if}}

May be this could work (Not tested)

Thanks for the follow-up here.

I’m surprised Forest doesn’t have the means to check locally as it does when checking for routes, models, etc. For these files, we simply need to do something like import { previewUserDataHook } from 'utils/beaconUtils'; into our forest/someCollectionFile.js, and then we can use those methods throughout. I’m equally surprised that Forest also doesn’t have a views folder to store smart views, and then assigned them as we do with the actions within collections now. Food for thought. :slight_smile:

We already did a POC for smart views stored on the agent side but it’s not yet part of the short roadmap :wink:

1 Like

Let’s go!! :slight_smile: Excited to see it come to fruition… now we just need to get upgraded to the next release so we’re ready for it when it comes out! :wink:

@vince On a similar note with this, I’m trying to add a call to lianaServerFetch to remove the need to pull in a Util method at all, and instead call a route that can handle doing all the work needed. It seems though that I can’t post to a route using lianaServerFetch. Can you confirm this?

In my case I’m trying to build out a URL per item in my smart view like so:

// component.js - smartview
const response = await this.lianaServerFetch.post('forest/actions/generate-vip-link', { userStubId: suggestedTalentStub['forest-UserStub'].id });

// suggestedTalentStub routes 
router.post('/actions/generate-vip-link',
  async (req, res) => {
    const { userStubId } = req.body;
    const { email } = req.user;

    // do some stuff
    return link;

Any thoughts on how to pull this off?

I was able to figure this one out:

  // Fetch the data from the API
      const response = await this.lianaServerFetch.fetch('/forest/api/smart-charts/chart-1', {
       method: 'POST',
       body: JSON.stringify(args)
      });
      this.data = await response.json();