Handlebars.js: {{#switch}} ajudante

Criado em 22 dez. 2014  ·  15Comentários  ·  Fonte: handlebars-lang/handlebars.js

Isso é muito útil e acho que seria melhor se fosse nativo da biblioteca:

{{#switch state}}
    {{#case "page1" "page2"}}toolbar{{/case}}
    {{#case "page1" break=true}}page1{{/case}}
    {{#case "page2" break=true}}page2{{/case}}
    {{#case "page3" break=true}}page3{{/case}}
    {{#default}}page0{{/default}}
{{/switch}}

Comentários muito úteis

Esta página é atualmente o terceiro resultado de pesquisa do Google para "Handlebars switch helper". Para o benefício das pessoas que chegam aqui de um mecanismo de pesquisa, aqui está uma implementação de Chris Montrois que oferece suporte a cláusulas de valor único case , como {{#case "page1"}} :

Handlebars.registerHelper("switch", function(value, options) {
    this._switch_value_ = value;
    var html = options.fn(this); // Process the body of the switch block
    delete this._switch_value_;
    return html;
});

Handlebars.registerHelper("case", function(value, options) {
    if (value == this._switch_value_) {
        return options.fn(this);
    }
});

Aqui está um case helper aprimorado que oferece suporte a cláusulas com um número variável de valores, como {{#case "page1" "page2"}} :

Handlebars.registerHelper("case", function() {
    // Convert "arguments" to a real array - stackoverflow.com/a/4775938
    var args = Array.prototype.slice.call(arguments);

    var options    = args.pop();
    var caseValues = args;

    if (caseValues.indexOf(this._switch_value_) === -1) {
        return '';
    } else {
        return options.fn(this);
    }
});

Todos 15 comentários

Isso é algo que pode ser alcançado (de uma maneira hacky) usando ajudantes padrão. Queremos manter os helpers integrados relativamente leves, em vez de permitir que terceiros implementem os helpers de que precisam, da maneira que melhor lhes convier, usando a API do helper.

Esta página é atualmente o terceiro resultado de pesquisa do Google para "Handlebars switch helper". Para o benefício das pessoas que chegam aqui de um mecanismo de pesquisa, aqui está uma implementação de Chris Montrois que oferece suporte a cláusulas de valor único case , como {{#case "page1"}} :

Handlebars.registerHelper("switch", function(value, options) {
    this._switch_value_ = value;
    var html = options.fn(this); // Process the body of the switch block
    delete this._switch_value_;
    return html;
});

Handlebars.registerHelper("case", function(value, options) {
    if (value == this._switch_value_) {
        return options.fn(this);
    }
});

Aqui está um case helper aprimorado que oferece suporte a cláusulas com um número variável de valores, como {{#case "page1" "page2"}} :

Handlebars.registerHelper("case", function() {
    // Convert "arguments" to a real array - stackoverflow.com/a/4775938
    var args = Array.prototype.slice.call(arguments);

    var options    = args.pop();
    var caseValues = args;

    if (caseValues.indexOf(this._switch_value_) === -1) {
        return '';
    } else {
        return options.fn(this);
    }
});

Muito bom, curto e doce. Eu já encontrei muitos mais longos no passado.

Algumas coisas a serem adicionadas podem ser {{#default}} {{/default}} e {{#case "value" break=true}} .

@stevenvachon Conforme solicitado;)

module.exports = {
    switch: function(value, options) {
        this._switch_value_ = value;
        this._switch_break_ = false;
        var html = options.fn(this);
        delete this._switch_break_;
        delete this._switch_value_;
        return html;
    },
    case: function(value, options) {
        var args = Array.prototype.slice.call(arguments);
        var options    = args.pop();
        var caseValues = args;

        if (this._switch_break_ || caseValues.indexOf(this._switch_value_) === -1) {
            return '';
        } else {
            if (options.hash.break === true) {
                this._switch_break_ = true;
            }
            return options.fn(this);
        }
    },
    default: function(options) {
        if (!this._switch_break_) {
            return options.fn(this);
        }
    }
};

@ Billy- Onde devemos incluir isso?

@jimkoul Essas são funções auxiliares, portanto, dependem de sua configuração.

Minha configuração (com Gulp + gulp-hb) suporta a especificação de um padrão glob para arquivos js que exportam funções auxiliares, como acima, assim fica assim:

// ...
.pipe(handlebars({
  helpers: 'handlebars/helpers/*.js'
})
// ...

Se você ainda não tiver certeza, faça uma pequena pesquisa sobre como as funções auxiliares funcionam com o guidão e como implementá-las com qualquer implementação de guidão que você esteja usando.

Seria bom se pudéssemos passar a variável pelo nome do switch e não precisarmos escrever um {{assign}} completo

Além disso, também estou recebendo uma mensagem indefinida, embora a variável esteja mudando corretamente quando o caso é encontrado.

Isso é o que eu tenho como ajudante

"use strict";
Handlebars.registerHelper("switch", function(value, options) {
    this._switch_value_ = value;
    this._switch_break_ = false;
    var html = options.fn(this);
    delete this._switch_break_;
    delete this._switch_value_;
    return html;
});

Handlebars.registerHelper("case", function(value, options) {
    var args = Array.prototype.slice.call(arguments);
    var options    = args.pop();
    var caseValues = args;

    if (this._switch_break_ || caseValues.indexOf(this._switch_value_) === -1) {
        return '';
    } else {
        if (options.hash.break === true) {
            this._switch_break_ = true;
        }
        return options.fn(this);
    }
});

Handlebars.registerHelper("default", function(options) {
    if (!this._switch_break_) {
        return options.fn(this);
    }
});

Isto é o que tenho em meu arquivo hbs:

{{#assign "testParam"}}foo{{/assign}}
{{#switch testParam}}
    {{#case "boo"}}{{#assign "testParam"}}case1 has been met{{/assign}}{{/case}}
    {{#case "foo" break=true}}{{#assign "testParam"}}case2 has been met{{/assign}}{{/case}}
    {{#case "tried" break=true}}{{#assign "testParam"}}case3 has been met{{/assign}}{{/case}}
    {{#case "bwahahaha" break=true}}{{#assign "testParam"}}case4 has been met{{/assign}}{{/case}}
    {{#default break=true}}{{#assign "testParam"}}nothing matched{{/assign}}{{/default}}
{{/switch}}

{{#ttpartial "testSwitch.content"}}
        {{testParam}}
{{/ttpartial}}

ou algum motivo acima faz com que o padrão sempre tenha precedência, mesmo quando um dos casos acima for atendido.

Aqui está o que eu uso:

Handlebars.registerHelper('switch', function(name, value, options) {
    this['_switch_value_' + name] = value;
    this['_switch_break_' + name] = false;
    var html = options.fn(this);
    delete this['_switch_break_' + name];
    delete this['_switch_value_' + name];
    return html;
});
Handlebars.registerHelper('case', function(name, value, options) {
    var args = Array.prototype.slice.call(arguments);
    var options    = args.pop();
    var caseValues = args;

    if ( this['_switch_break_' + name] || caseValues.indexOf(this['_switch_value_' + name]) === -1) {
        return '';
    } else {
        this['_switch_break_' + name] = true;
        return options.fn(this);
    }
});
Handlebars.registerHelper('default', function(name, options) {
    if ( !this['_switch_break_' + name] ) {
        return options.fn(this);
    }
});

Os switches são nomeados, portanto, é possível ramificá-los (imbricação? Não tenho certeza sobre a palavra ...)
Além disso, a pausa é sempre feita quando uma condição é atendida

ie:

    {{#switch "1" "aaa"}}
        {{#case "1" "aaa"}}
            {{#switch "2" "bbb"}}
                {{#case "2" "bbb"}}ok{{/case}}
            {{/switch}}
        {{/case}}
        {{#default "1"}}nok{{/default}}
    {{/switch}}

Tenho certeza de que não estou entendendo como isso funciona, então peço desculpas pela minha confusão, mas ... É possível que o switch funcione dentro de each ? Tenho experimentado, mas continuo recebendo erros.

Aqui está o que eu tenho:

{{#each columns}}
    {{#switch this}}
        {{#case 'foo'}}
        {{/case}}
        {{#case 'bar'}}
        {{/case}}
    {{/switch}}
{{/each}}

Mas estou entendendo:

Uncaught TypeError: Cannot create property '_switch_value_' on string 'name'

Parece-me que this deve ser algo diferente do que é esperado, mas eu realmente não sei.

Parece que consegui fazê-lo funcionar alterando o switch seguinte forma:

Handlebars.registerHelper({
    switch: function(value, options) {
        return options.fn({
            _switch_value_: value,
            _switch_break_: false
        });
    },
    //...
});

Mas acho que estou perdendo algo para outros casos. Dito isso, eu sempre poderia anexar esses valores a options e acho que funcionaria.

@ Billy- @ a-le?

@infinityplusone, infelizmente, não uso o guidão adequadamente há anos, então imagino que a implementação do helper pode ter mudado muito desde que escrevi isso, provavelmente por isso não estava funcionando como o esperado. Eu não tenho certeza, lamento desapontar.

@infinityplusone Se você usar minha versão, terá que "nomear" o switch.
Então, com seu exemplo:

{{#each columns}}
    {{#switch "myswitch" this}}
        {{#case "myswitch" 'foo'}}
        {{/case}}
        {{#case "myswitch" 'bar'}}
        {{/case}}
    {{/switch}}
{{/each}}

para bloco de switch aninhado

Handlebars.__switch_stack__ = [];

Handlebars.registerHelper( "switch", function( value, options ) {
    Handlebars.__switch_stack__.push({
        switch_match : false,
        switch_value : value
    });
    var html = options.fn( this );
    Handlebars.__switch_stack__.pop();
    return html;
} );
Handlebars.registerHelper( "case", function( value, options ) {
    var args = Array.from( arguments );
    var options = args.pop();
    var caseValues = args;
    var stack = Handlebars.__switch_stack__[Handlebars.__switch_stack__.length - 1];

    if ( stack.switch_match || caseValues.indexOf( stack.switch_value ) === -1 ) {
        return '';
    } else {
        stack.switch_match = true;
        return options.fn( this );
    }
} );
Handlebars.registerHelper( "default", function( options ) {
    var stack = Handlebars.__switch_stack__[Handlebars.__switch_stack__.length - 1];
    if ( !stack.switch_match ) {
        return options.fn( this );
    }
} );
{{#switch state}}
    {{#case "page1" "page2"}}page 1 or 2{{/case}}
    {{#case "page3"}}page3{{/case}}
    {{#case "page4"}}page4{{/case}}
    {{#case "page5"}}
            {{#switch s}}
                {{#case "3"}}s = 3{{/case}}
                {{#case "2"}}s = 2{{/case}}
                {{#case "1"}}s = 1{{/case}}
                {{#default}}unknown{{/default}}
            {{/switch}}
    {{/case}}
    {{#default}}page0{{/default}}
{{/switch}}
var data = {
    state : 'page5',
    s : '1'
};

var html = template( data );

Que tal agora?
apenas se você deseja converter a chave em valor.

`` `` javascript
module.exports = function (input, cases, values) {
const caseArray = cases.split (',')
const valueArray = values.split (',')
const index = caseArray.indexOf (input)

return valueArray [index]
};
Guiador
{{mudar "S" "S, N, D", "SIM, NÃO, EXCLUÍDO"}}
`` ``

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

ShintaroOkuda picture ShintaroOkuda  ·  7Comentários

jasonh-brimar picture jasonh-brimar  ·  6Comentários

fcpauldiaz picture fcpauldiaz  ·  4Comentários

morgondag picture morgondag  ·  5Comentários

stevenvachon picture stevenvachon  ·  7Comentários