Handlebars.js: Kann ich mehrere Helfer in einem einzigen Tag verwenden?

Erstellt am 7. Sept. 2012  ·  17Kommentare  ·  Quelle: handlebars-lang/handlebars.js

wie {{ helper1 helper2 text }} , wissen Sie, dass manchmal nur ein Helfer nicht ausreicht, um die Arbeit zu erledigen.

Hilfreichster Kommentar

Dies scheint eine native Unterstützung zu haben, die Folgendes verwendet:

{{ helper1 (helper2 text) }}

Alle 17 Kommentare

Ich denke, es müsste eine Möglichkeit geben, Ausdrücke zu verschachteln, etwa wie folgt: {{headerText {{getTitle "my_page"}}}} .

Das wird derzeit nicht unterstützt und ich habe auch nicht vor, es zu unterstützen.

Sie könnten jedoch theoretisch einen Helfer erstellen, der andere Helfer absichtlich verbraucht und verkettet:

{{chain "helper1" "helper2" text}}

Falls es jemanden interessiert, ich habe so einen Helfer erstellt:

Handlebars.registerHelper('chain', function () {
    var helpers = [], value;
    $.each(arguments, function (i, arg) {
        if (Handlebars.helpers[arg]) {
            helpers.push(Handlebars.helpers[arg]);
        } else {
            value = arg;
            $.each(helpers, function (j, helper) {
                value = helper(value, arguments[i + 1]);
            });
            return false;
        }
    });
    return value;
});

Funktioniert so:

{{chain "taxAdd" "formatPrice" this.product.price}}

@Znarkus , das eine Abhängigkeit von jQuery einführt

@jrajan Ich habe nur jQuery.each können es nach Ihren Wünschen neu schreiben.

Wenn jemand an einer agnostischen jQuery-Version interessiert ist:

Handlebars.registerHelper('chain', function() {
  var helpers = [];
  var args = Array.prototype.slice.call(arguments);
  var argsLength = args.length;
  var index;
  var arg;

  for (index = 0, arg = args[index];
       index < argsLength;
       arg = args[++index]) {
    if (Handlebars.helpers[arg]) {
      helpers.push(Handlebars.helpers[arg]);
    } else {
      args = args.slice(index);
      break;
    }
  }

  while (helpers.length) {
    args = [helpers.pop().apply(Handlebars.helpers, args)];
  }

  return args.shift();
});

Ein Problem bei beiden Implementierungen ist erwähnenswert: Wenn eines der Argumente als Werte gedacht ist, die an einen Helfer übergeben werden sollen, aber zufällig auch Zeichenfolgen sind, die dem Namen eines vorhandenen Helfers entsprechen, gibt es unerwartete Ergebnisse.

Hier sind zwei Implementierungen. Bei beiden können Sie im Gegensatz zu den vorherigen Beispielen mehrere Argumente an jeden Helfer senden.
Sie sind auch in Kaffeeschrift geschrieben und hängen von Unterstrich oder Lodash ab.

Mit der ersten können Sie Folgendes tun:
{{{chain 'join-strings' 'link-twitter-handles' '@' twitterUsername}}}
Aber so etwas würde zu unerwarteten Ergebnissen führen:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}

Handlebars.registerHelper 'chain', ->
    # Get rid of the options hash
    args = Array.prototype.slice.call arguments, 0, -1
    helpers = []
    argsForHelpers = null
    value = undefined

    _.each args, (arg, i) ->
        if Handlebars.helpers[arg]
            helpers.push Handlebars.helpers[arg]
        else if not value # Only call the helpers once
            value = arg
            unless argsForHelpers
                argsForHelpers = args[i+1..-1]
                argsForHelpers.unshift value
            _.each helpers, (helper) ->
                argsForHelpers[0] = value
                value = helper.apply null, argsForHelpers

    value

Dieses zweite Beispiel hat ein Trennzeichen, mit dem chain die Helfer von den Argumenten trennen lässt.
Der Helfer geht davon aus, dass jedes Argument vor dem Trennzeichen ein Helfer ist und alle anderen als Argumente an die Helfer übergeben werden sollen.

Handlebars.registerHelper 'chain', ->
    # Get rid of the options hash
    args = Array.prototype.slice.call arguments, 0, -1
    helpers = []

    for arg,i in args
        if arg is '--'
            argsForHelpers = args.slice i + 1
            value = argsForHelpers[0]
            break
        else
            helpers.push Handlebars.helpers[arg]

    _.each helpers, (helper) ->
        argsForHelpers[0] = value
        value = helper.apply null, argsForHelpers

    value

Angesichts dieser Vorlage:
{{{chain 'join-strings' 'link-twitter-handles' '@' 'join-strings' twitterUsername}}}
und dieses Objekt:
{twitterUsername: 'abc'}
Wir könnten eine kompilierte Vorlage wie diese erwarten:
<a href="https://twitter.com/join-stringsabc">@join-stringsabc</a>

Ich habe die Implementierung von

/**
 * Takes an arbitrary number of arguments, the first of which is the operation type 'AND' or 'OR'.
 * Following that will be a list of block helper names prefixed by '!!'.
 * Calls each block helper with the remaining arguments.
 *
 * <strong i="7">@returns</strong> {string}  returns options.fn(this) or options.inverse(this) depending on result of each helper and operation type
 */
Handlebars.registerHelper('chainBlockHelpers', function() {
    var index, arg, helperResult, pass,
        helpers = [],
        args = Array.prototype.slice.call(arguments),
        argsLength = args.length,
        options = args[argsLength-1],
        operation = args.shift(),
        passVal = options.fn(this),
        failVal = options.inverse(this);

    if (operation !== 'AND' && operation !== 'OR')
        throw new Error ('chainBlockHelpers only supports "AND" or "OR" operations.')

    for (index = 0, arg = args[index]; index < argsLength; arg = args[++index]) {
        if (typeof arg == 'string' && arg.startsWith('!!') && Handlebars.helpers[arg.substr(2)]) {
            helpers.push(Handlebars.helpers[arg.substr(2)]);
        } else {
            args = args.slice(index);
            break;
        }
    }

    if (operation === 'AND') {
        pass = true;
        while (helpers.length) {
            helperResult = helpers.pop().apply(Handlebars.helpers, args);
            if (helperResult == failVal) {
                pass = false;
                break;
            }
        }
    } else {
        pass = false;
        while (helpers.length) {
            helperResult = helpers.pop().apply(Handlebars.helpers, args);
            if (helperResult == passVal) {
                pass = true;
                break;
            }
        }
    }

    return pass ? passVal : failVal;
});

Dies scheint eine native Unterstützung zu haben, die Folgendes verwendet:

{{ helper1 (helper2 text) }}

In einigen Fällen können Sie Ihre Helfer wie folgt arbeiten lassen:

{{#helper1}}{{helper2}}content{{/helper2}}{{/helper1}}

@Znarkus Wenn

    Handlebars.registerHelper('shortNumber', function (value) {
        //return new Handlebars.SafeString(iSpot.number.shortNumber(value)); // Breaks
        return iSpot.number.shortNumber(value);  // Works
    });
    Handlebars.registerHelper('asDollars', function (value) {
        //return new Handlebars.SafeString(iSpot.number.asDollars(value)); // Breaks
        return iSpot.number.asDollars(value); // Works
    });

+1 @amwmedia- Ansatz - {{pluralize (titleize (humanize schema.name))}}

+1, das sieht nach einer schönen sauberen Syntax aus.

+1 @amwmedia Funktioniert perfekt danke

@breandr / @amwmedia Ansatz funktioniert wie ein Charme, aber nur ohne Handlebars.SafeString() wie @cssagogo oben erwähnt.

Du kannst also etw tun. mögen:

{{> partial text=(concat value (default extension 'PDF')) }}

Danke

Ich bin selbst auf dieses Problem gestoßen. Ich weiß, dass ich wirklich spät dran bin, aber ich habe eine Lösung, die für mich funktioniert hat. Bitte verzeihen Sie mir, wenn dies bereits erwähnt wurde (ich habe mir nicht die Zeit genommen, nachzusehen). Dies ist nicht die coolste Lösung und technisch gesehen keine direkte Antwort auf Ihre Frage, aber eine Lösung des Problems (mehrere Funktionen auf einem Wert ausführen).

Ich bewahre alle meine Hilfsfunktionen in einer separaten Datei auf. Da sie sich alle an derselben Stelle befinden, kann ich den Wert an einen Helfer übergeben und dann einfach alle anderen Funktionen aufrufen, die ich in der Datei meiner Helferfunktion habe. So:

{{ function1 value }}

Helferdatei

function2 (value) {
   // code
}

function1 (value) {
   // code
   function2(value)
   // code
   return value;
}

Dies ist natürlich eine einfache Möglichkeit, beliebig viele Funktionen nutzen zu können. Sie könnten sogar eine Basisfunktion festlegen, die als Ihr "Chainer" fungiert.

{{ chainer value }}

Helferdatei

function1 (value) {
   // code
}
function2 (value) {
   // code
}
function3 (value) {
   // code
}
function4 (value) {
   // code
}

function chainer(value) {
   function1(value)
   function2(value)
   function3(value)
   function4(value)
   return value;
}

Ich habe das selbst noch nicht gemacht, aber ich sehe nicht, warum es nicht funktionieren sollte.

Hinweis Sie müssen nur die Funktionen, die Sie in Ihrem HTML-Code verwenden möchten, als Lenker-Helfer registrieren. Ich persönlich habe meine alle registriert, weil ich sie unabhängig voneinander verwende, aber Sie müssen es nicht, wenn Sie nicht davon ausgehen, dass Sie es direkt verwenden müssen.

Ein Rückblick auf die prozedurale Programmierung :)

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

rhariraman picture rhariraman  ·  5Kommentare

rizen picture rizen  ·  6Kommentare

LengYXin picture LengYXin  ·  3Kommentare

DylanPiercey picture DylanPiercey  ·  7Kommentare

sontek picture sontek  ·  3Kommentare