2011-01-17 12 views
43

Używam Express.js (na Node.js) i wiem, że można renderować widok z niestandardowymi danymi za pośrednictwem parametru "locals". (res.render("template", { locals: { foo: "bar" } });)Express.js Wyświetl "globals"

Czy istnieje sposób na "globals"? (dane dostępne dla każdego widoku)

Widziałem view options, ale to nie jest rekursywne, więc zastępuje locals, które ustawiłem, jeśli używam dowolnych locals z moim szablonem.

To jest mój przypadek użycia: chcę, aby pliki CSS/JS mogły być dodawane na stronie, a to jest część mojego głównego layoutu. Problem polega na tym, że jeśli nie ustawię tych tablic bezpośrednio przy każdym renderowaniu, otrzymam niezdefiniowany błąd, więc w moim szablonie zawsze muszę wykonać taniec typeof css !== "undefined". Dodatkowo mam inne listy opcji wyboru skrzynki, których nie chcę dodawać jawnie do każdego z moich formularzy.

+0

nie można zrobić to poprzez zdefiniowanie zmiennej o zasięgu globalnym (jak przez swoje wymagać oświadczenia) i odwoływanie się do niego w jednym z wywołań app.get? – Stephen

+1

Tak, ale nadal muszę jawnie przekazywać te dane w każdym wywołaniu funkcji 'render()'. –

+2

LOL!Szukałem tego rozwiązania, a tu znowu jestem w butach, z powrotem w Jan. Dzięki za zadanie tego pytania! – Stephen

Odpowiedz

56

Warto zauważyć, że dla tych, którzy mogli natknąć się na to pytanie od czasu wydania Express 3, że metoda "dynamicHelpers" już nie istnieje.

Zamiast tego można użyć funkcji app.locals, która działa jako obiekt, w którym można przechowywać wartości lub funkcje, a następnie udostępnia je do widoków. Na przykład: -

// In your app.js etc. 
app.locals.title = "My App"; 
app.locals({ 
    version: 3, 
    somefunction: function() { 
     return "function result"; 
    } 
}); 

// Then in your templates (shown here using a jade template) 

=title 
=version 
=somefunction() 

// Will output 

My App 
3 
function result 

Jeśli potrzebujesz dostępu do obiektu żądania, aby wyciągnąć informacje z możesz napisać prostą funkcję middle-ware i użyć zmiennej Ustawien.

Na przykład, jeśli używasz connect-błysk dostarczenie wiadomości do użytkowników, możesz zrobić coś takiego:

app.use(function(req, res, next) { 
    app.set('error', req.flash('error')); 
    next(); 
}); 

co dałoby dostęp do komunikatu o błędzie z = settings.error w twój szablon.

Te tematy są tutaj, aczkolwiek nieznacznie krótko: http://expressjs.com/api.html#app.locals

Aktualizacja: Express 4

app.locals jest teraz prosty obiekt JavaScript, więc każda nieruchomość musi być ustawione jeden za drugim.

app.locals.version = 3; 
app.locals.somefunction = function() { 
    return "function result"; 
} 

res.locals zapewnia dokładnie taką samą funkcjonalność, z wyjątkiem należy stosować do danych żądania specyficznych danych aplikacji, a nie całej. Obiekt lub ustawienia użytkownika są częstym przypadkiem użycia.

res.locals.user = req.isAuthenticated() ? req.user : null; 
res.locals.userSettings = { 
    backgroundColor: 'fff' 
} 
+5

Najlepsze wyjaśnienie, które znalazłem. I myślałem. Dzięki. –

+0

app.set ("błąd", msg) ustawił błąd dla CAŁKOWITEGO wniosku, a nie tylko dla użytkownika, który złożył wniosek, czy też się mylę? – vegetable

+0

Twoje wyjaśnienia są fantastyczne. Ale gdy próbuję wyświetlić zmienne globalne w moim pliku Jade za pomocą "= title", nic się nie pojawiło. W tym celu powinienem użyć następującej synthaksu "# {title}", aby poprawnie wyświetlić moją zmienną. – JohnDoe66

1

Najprostszym sposobem osiągnięcia tego jest utworzenie zmiennej, która reprezentuje domyślny zestaw locali dla swoich widoków. Następnie utwórz funkcję, która akceptuje obiekt, łączy go z lokalnymi i zwraca scalony obiekt.

ja też przekazać wszystkie moje mieszkańców wewnątrz obiektu kontenera tj {locals:{g:{prop:val}}} więc w moich poglądów mogę refernce g.prop które będą po prostu wrócić null gdy nie jest ustawione, zamiast rzucania niezdefiniowany błąd.

function default_page_vars(custom_vars){ 
    var vars = { 
     footer: true, 
     host: req.headers.host.split(':')[0], 
     config: this.config 
    }; 

    if(custom_vars){ 
     for(var k in custom_vars){ 
      vars[k] = custom_vars[k]; 
     } 
    } 
    return { 
     g:vars 
    }; 
} 

//within your handler 
response.render(view, { 
    locals: default_page_vars(other_locals) 
}); 
4

I skończyłem patrząc do kodu źródłowego, a ja rzeczywiście okazało się, że jest to obecnie możliwe, w które nigdy nie wersji Express. (do tej pory dostępne tylko przez GitHub)

+0

Czy mógłbybyś podzielić się linkiem ze znalezionym źródłem? Próbuję zrobić to samo. Dzięki. – luisgo

+1

Obecna wersja (v2 +) pozwala na 'app.set (" opcje widoku ", {... wartości domyślne ...});' –

+0

@dominic jakie są wartości domyślne? lub przynajmniej gdzie są wymienione? – talentedmrjones

10

Istnieje sposób na posiadanie zmiennych "globalnych" dla widoków przy użyciu pomocników widoku dynamicznego.

z prowadnicy Express.js:

app.dynamicHelpers (obj)

Rejestry dynamiczny widok pomocników. Pomocnicze widoki dynamiczne to po prostu funkcje , które akceptują parametry req, res i są oceniane przed wystąpieniem Server przed renderowaniem widoku. Wartość zwracana tej funkcji staje się zmienną lokalną, z którą jest powiązana .

app.dynamicHelpers ({sesja: funkcja (req, res) { return req.session;}});

Wszystkie widoki będzie teraz mieć sesję dostępne tak, że dane sesji mogą być dostępne za pośrednictwem session.name etc:

można znaleźć prawdziwy przykład, w jaki sposób ich używać tutaj: https://github.com/alessioalex/Nodetuts/tree/master/express_samples (węzeł app.js aby uruchomić aplikację)

+0

To zadziałało cuda dla mnie, dzięki! +1 – talentedmrjones

7

przykładem w świecie rzeczywistym z użyciem opcji widoku jako autor wymienić:

var app = express.createServer(); 

app.configure(function() { 
    app.set('views', path.join(__dirname, '..', 'views')); 
    app.set('view engine', 'jade'); 
    app.set('view options', { 
    assetVersion: 1 
    }); 

A potem w moim układzie.Jade (szablon bazowy dla aplikacji w moim przypadku):

link(rel='stylesheet', href='/static/css/' + assetVersion + '/style.css') 
script(src='/static/js/' + assetVersion + '/script.js') 

Dzięki tej małej sztuczki, mam tylko zaktualizować zmienną jedno miejsce assetVersion, aby upewnić się, że moje aktywa nie są buforowane w lakier lub innych miejscach.

0

To jest zakopana odpowiedź, ale w końcu udało mi się ją uruchomić.

1) Jest to przykład wokół modułu Przyłączenie rzutowej

2) Dodanie elementu warstwy pośredniej w server.js/app.js dodać req do locals. Dzięki temu szablon może zadzwonić pod numer request.flash(), gdy zajdzie taka potrzeba. Bez tego, flash() zostaje zużyte na każde żądanie/przekierowanie pokonując cel.

var app = module.exports = express() 
    , flash=require('connect-flash'); 
app.configure(function(){ 
    ... 
    app.use(express.session({ secret: "shhh" })); 

    // Start Router 
    app.use(flash()); 
    app.use(function(req, res, next) { 
    res.locals.request = req; 
    next(); 
    }); 

    app.use(app.router); 
}); 

3) Konfiguracja trasy jako normalne (jest to coffeescript, ale nic specjalnego)

app.get '/home', (req, res) -> 
    req.flash "info", "this" 
    res.render "#{__dirname}/views/index" 

4) request.flash call(), gdy chcemy wiadomości. Są one spożywane każdego połączenia, więc ich nie console.log albo oni znikną :-)

!!! 
html 
    head 
    title= config.appTitle 
    include partials/_styles 

    body 
    include partials/_scripts 

    #header 
     a(href="/logout") Logout CURRENTUSER 
     h2= config.appTitle 

    #messages 
     - var flash = request.flash() 
     each flashType in ['info','warn','error'] 
     if flash[flashType] 
      p.flash(class=flashType) 
      = flash[flashType] 


    block content 
     h1 content here 
+0

Nie polecam przekazywania całego obiektu żądania. // zawsze dołączamy flasha app.use (function (req, res, next) { res.locals.flasher = {}; res.locals.flasher.flash = req.flash; res.locals.flasher.session = req.session; next(); }); – Setheron