Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using the drupal-attribute class as an async Twing function #12

Closed
philwolstenholme opened this issue Jul 9, 2021 · 7 comments
Closed

Comments

@philwolstenholme
Copy link

philwolstenholme commented Jul 9, 2021

(This is a duplicate of me asking the same question at NightlyCommit/twing#535)

I'm trying to use this package alongside Twing in Storybook to demonstrate Twig templates that will be used on a Drupal 9 site. The Drupal templates contain a lot of this sort of thing: {% set attributes = attributes|default(create_attribute()) %} and I'd like to be able to use the Attribute class inside Storybook. Is this possible? If so I would love some help as I've been stuck on this for a while and I am reaching the limits of my JavaScript knowledge in this area.

I am using drupal-attribute 1.0.2, Twing 5.0.2 and twing-loader 0.5.5.

In my Twing environment file I am defining a create_attribute function like this:

const drupalAttribute = require('drupal-attribute');

const createAttribute = new TwingFunction('create_attribute', () =>
  return Promise.resolve(new drupalAttribute()),
);

const environment = new TwingEnvironment(loader, { autoescape: false });
environment.addFunction(createAttribute);

module.exports = environment;

My templates are rendering, but with no attributes, so I know I am doing something wrong. There's no TwingErrorSyntax: Unknown "create_attribute" function error though. It looks like my create_attribute function can be found, but it is not usable by the templates because of how I have set things up at the moment.

My templates are pretty basic, they look like this sort of thing:

{% set attributes = attributes|default(create_attribute()) %}
{% set attributes = attributes.addClass(['btn']) %}

<button {{ attributes }}>Stripped down example</button>

Twing and using the JavaScript version of create_attribute() is new to me and I have a feeling I'm doing something silly. Is Promise.resolve(new drupalAttribute()), likely to work or am I being over optimistic here? I read something about classes not being callable? I know this isn't a Twing issue (sorry) but I wondered if anyone here had encountered the same issue, especially as Eric is also a Twing maintainer.

Other things I have tried

const createAttribute = new TwingFunction('create_attribute', () => {
  const create_attribute = new drupalAttribute();
  return Promise.resolve(create_attribute);
});
const createAttribute = function() {
  return Promise.resolve(() => {
    return new drupalAttribute();
  });
};

environment.addFunction(new TwingFunction('create_attribute', createAttribute));
@JohnAlbin
Copy link

@philwolstenholme I've added the glue necessary to use Attribute inside Twing as part of https://github.com/JohnAlbin/drupal-twig-extensions

Even if you don't use that package, you can probably re-use some of its GPL code.

@ericmorand
Copy link
Owner

@JohnAlbin amazing!!!

@philwolstenholme
Copy link
Author

Thanks @JohnAlbin that's great! I'll pass this on to the team who are working on the project that I initially raised this question about. How did you get it working in the end, I'm interested in how far off I was! 😄 I'll take a look at the code next week and see if I can spot what I was missing.

@tjheffner
Copy link

@philwolstenholme Did you/your team ever get attributes printing properly in Storybook HTML?

I'm able to render .twig templates using Twing (thanks to the approach from @MichaelAllenWarner in https://github.com/MichaelAllenWarner/dte-storybook) but the attributes never appear to print for me.

import block from './block.twig';
import drupalAttribute from 'drupal-attribute'
import './block.css';
import './block.js';

export default { title: 'Blocks' };

export const Block = (_, { loaded: { component } }) => component;

Block.args = {
  attributes: new drupalAttribute(),
  title_attributes: new drupalAttribute(),
  plugin_id: "Some plugin",
  title_prefix: "",
  title_suffix: "",
  label: "I'm a block!",
  content: "Lorem ipsum dolor sit amet.",
  configuration: {
    provider: "Some module"
  }
}

Block.render = async args => {
  return await block({
    ...Block.args
  })
}

other args come through just fine, but the attributes are dropped:

<div>
      <h2>I'm a block!</h2>
    
      Lorem ipsum dolor sit amet.
  </div>

@tjheffner
Copy link

@MichaelAllenWarner ah, I should have checked the other branches 😅 your repo has been extremely helpful as a reference. thank you!!

@MichaelAllenWarner
Copy link

@tjheffner I only just made it in response to your question (got me curious).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants