Getting the intermix just right (mixing SSJS and WCTL)

It's possible to call WCTL macros from a page being constructed in SSJS, and vice-versa. Here's how, along with a few tips to avoid the potholes on your journey:

Calling WCTL from SSJS:
  1. To call a WCTL macro from SSJS, use the wctlEval syntax:

    bb += wctlEval( 'use myWCTLMacroName' );

  2. Remember that you can't send function parameters in WCTL, so you may need to set a WCTL variable before calling your WCTL function:

    setWctlVar( 'myWctlVarName', value );

  3. Because WCTL has only one variable type, strings, make sure that the value in your setWctlVar() statement is a string.  WCTL can do integer math on strings, so don't worry that point if your WCTL macro needs to do any simple calculations.

  4. You can also get a WCTL variable value from JS using wctlVar:

    wctlVar( 'myWCTLVarName' );

  5. If, for some reason, you need to evaluate a chunk of WCTL which includes %%'s, you can use an alternative wctlEvalTemplate syntax:

    wctlEvalTemplate( "%" + "% if red %" + "%" + "red" + "%" + "% endif %" + "%" );

    (In other words, evaluate: %% if red %%red%% endif %%) As you can see, the syntax is a bit ridiculous because %% has a specific meaning within SSJS, so you have to divide up the individual %'s in order to get it to work.  This isn't used much because it's usually easier to just make it a macro and call with wctlEval.

Calling SSJS from WCTL:
  1. To call an arbitrary SSJS expression from WCTL, us the jsEval syntax:

    %% "if ( user ) { + 'Hello ' + user.userName; }".jsEval %%

  2. But if you want to specifically call an SSJS command or function, it's more efficient to use the jsCall syntax:

    %% "mySSJSCommandOrFunctionName".jsCall( "param1", param2 ) %%

    You can send as many parameters as you need to.  Parameters can be either WCTL variables or literals.

  3. If your SSJS is a command and doesn't have any parameters (this won't work with functions), you can alternatively call your SSJS like you would any WCTL macro:

    %% use mySSJSCommandName %%

  4. If your SSJS function or command is returning a numeric value, convert that number to a string in the SSJS function before returning it to WCTL.  If you don't, it will be blank because WCTL won't know what to do with it.

And now, the potholes:
  1. Any SSJS function mixed with WCTL macro needs to be constructed so that it concatenates the page response to a ByteBuffer and then returns the ByteBuffer at the end of the function.  If you don't do that, you run the risk of A Very Weird Thing(tm) when the page elements come out in the wrong order because of differences in the way the response buffer is handled in WCTL and SSJS.

    So do this:

    var bb = new ByteBuffer();
    bb += "Hello, world!";
    return bb;


    And not this:

    + "Hello, world!";

  2. Usually, WCTL and SSJS will track the "current location" such that the value of %% location %% in WCTL will be the same as the SSJS location.storedUniqueId. However, once in a while, they can get out of synch. In any case, if you are having problems with the current location not being what you think it should be, you can set it in WCTL setPath( someLocationId ) or in SSJS location = someNodeObject. In SSJS if you only have the unique ID of the location you'll need to get the object from the unique ID first:

    location = Node.lookup( 'someUniqueId' );
So off you go, on your journey. Keep the intermix just right and you'll get along just fine.

No comments:

Post a Comment