I started learning closure javascript template library .
Is it possible to create local variable inside a closure template soy file ?
I tried using
$i=1;
but it prints $i=1 on screen in place of declaring it.
I had looked inside examples at
http://code.google.com/p/closure-templates/source/browse/trunk/examples/features.soy
but didn't find same type of example.
Yes, this is now possible! If you have a build of Closure Templates that was cut in 2011, you can declare local variables as follows:
{let $first: $person.firstName /}
{$first}
Note that like {param}, you can also define a local variable with a more complex expression between opening and closing tags:
{let $name}
{$person.firstName} {$person.lastName}
{/let}
Sometimes you need to use this form if you want to use other commands to define your variable:
{let $className}
{css name_class}
{/let}
<div class="{$name_class}"></div>
For more information about using let visit project's documentation
Related
I'm working on a Laravel app that I'm transitioning to React using a microfrontend(-like?) approach. I defined a helper function in Laravel that receives a component name and array of props and outputs the server-side rendered React HTML. I then call this function inside my views where needed.
Each page in my application defines a few variables that might affect the rendering both of these React components and also the Blade templates. So I define the variables in the view and send them to JavaScript land through a global window variable. But I also need these variables in the SSR helper.
Right now I have two ideas on how to do this:
Pass the variables as props in each call to my helper function. I want to avoid this as the variables will never change throughout the request lifecycle and all the #includes and #extends
Set the values using config helper before rendering the view. This seems kind of unidiomatic, as I think config should be used with more "static" values (that apply for the whole application and not particular pages), but I'm not very well versed in Laravel-world so this might actually be acceptable.
So right now I'm more inclined to 2, but I was wondering if there was a better option?
Some code:
my-template.blade.php
//these are the variables that I want to access in my helper
#extends('master.index', [
"_PAGE_CONFIG" => [
"page" => "blog",
"header" => ["search" => true]
]
]);
#section('content')
#include('some-template.that-also-has.ssr-components-in-it')
{!! ssr('blog/Blog', ["posts" => $posts]) !!}
#endsection
master/index.blade.php
<body>
#if($_PAGE_CONFIG["header"])
<header>{!! ssr('header/Header') !!}</header>
#endif
#yield('content')
<script>
//here I pass my variables to (client) JS land
window._PAGE_CONFIG = #json($_PAGE_CONFIG);
</script>
</body>
my-SSR-helper.php
function ssr($component, $props = []) {
/*
here I call a node server or script that handles the rendering for me,
but I want to pass it $_PAGE_CONFIG, which will be different in each page.
I could pass it in each ssr call in the template but this is what I want to avoid
as this function might be called several times down the #include/#extend chain
and $_PAGE_CONFIG never changes in any one page
(but might be different for different pages).
*/
}
If each page always gets the same values, then you should set an array somewhere into your config where the keys are the pages and the values are the props received. By the way, you would get:
function ssr($component, $page, $props = []) {
$pageProps = config('somewhere.'.$page);
}
I'm glad to see people using micro-frontends to use React to server-side rendering in a non-javascript framework like Laravel.
I recommend you take a look at this article Universal Rendering in Laravel using Vue.js and Ara Framework. Ara Framework supports also React, I think the server-side include approach is the best option to overcome the limitations of Blade.
This article can give you context about how this approach works.
https://itnext.io/strangling-a-monolith-to-micro-frontends-decoupling-presentation-layer-18a33ddf591b
Could you explain me how to use Lodash _.template in order to get some value from script to .html file via {{data}} ?
For example:
In script.js I set some changes to my data object and in view.html. I want to get changed data with {{data}}
How to use lodash _.template() for this issue?
The lodash template function does not allow you to build templates from files (but you could do it when combined with Webpack). It has absolutely nothing to do with AngularJS templates. However in some situations it makes sense of using inside of AngularJS, like for example building a list of strings with a pattern or the like.
You compile a template string to a function you can call as often as you like with the values:
const executor = _.template("Hello <%= name %>, my old friend!");
console.log(executor({name: 'Alice'})); // Hello Alice, my old friend!
console.log(executor({name: 'Bob'})); // Hello Bob, my old friend!
You can also use conditional, loops, etc.: https://lodash.com/docs/4.17.15#template
I am trying to see the value of a variable inside a function when the execution is paused at a debug point inside the function using chrome's developer tools .I selected/hovered over the variable but the tooltip with the value is not appearing unlike normal javascript function in other js files.
try type the variable name in console window, you should be able to see what is the variable value.
example :
Select the whole variable name and hover it again.
I couldn't find an answer or a solution to a challenge yet: How can I bind a variable (Session variable, no mongo collection) reactively in angular-meteor?
I'm converting from standalone meteor. Here I could use the template.helper method. As I can't use templates (and iron:router) anymore with angular-meteor and angularui-router, I can't bind reactivity to the helper anymore (at least in my understanding).
I tried this in an meteor-angular controller, which belongs to a sentence.tpl file:
$scope.parsestring = function(input_string){
tokenizer(input_string);
};
$scope.sentence_type = Session.getJSON("current_sentence.sentence_type");
Tokenizing works (I can see it in the debugger), but the value is only displayed, when I reload the page. What I want to achieve is tokenizing a string from an input field into a JSON representation (the tokenizer takes care of that) and displaying it similtaniously from the JSON representation in a structured way (separate html input elements, which are created dynamically). sentence_type is the variable that should be used on the html-page to show and change the sentence type, which can change while typing.
Anybody has some hints? Maybe, I could also use some Angular feature that I don't know?
Cheers,
Jan
Code repo:
My current code looks like this:
My code looks similar to this:
angular.module('ngaignt').controller("InteractorCtrl", ['$scope', '$meteor', '$meteorCollection',
function ($scope, $meteor, $meteorCollection) {
// Autorun is necessary to make reactive variables out of the JSON returns
var c = Tracker.autorun(function (comp) {
$scope.verb_type = Session.getJSON("current_verb.type");
$scope.object_type = Session.getJSON("current_object.type");
$scope.verb_attributes = _.toArray(Session.getJSON("current_verb.attributes"));
$scope.object_attributes = _.toArray(Session.getJSON("current_object.attributes"));
if (!comp.firstRun) {
// only do not do aply at first run becaulse then apply is already running.
$scope.$apply();
}
});
$scope.parsestring = function (input_string) {
interactor(input_string);
};
//$scope.on('$destroy', function () {c.stop()});
}]);
To use reactive variables, you need a reactive computation. You may need to use Tracker.autorun:
$scope.parsestring = Tracker.autorun(function(someStringInSession){
tokenizer(Session.get(someStringInSession));
});
Or you can use Tracker.autorun(func) wherever you use a reactive variable to reactively rerun a function when the variable changes.
good question and the best answer depend on your needs.
There are 2 possible solutions:
If you want to bind a Session variable to a scope variable, use the $meteorSession service.
What it does is that every time the scope variable will change, it will change to Session variable (and trigger an autorun if it's placed inside one).
and every time the Session variable will change, the scope variable will change as well (and change the view that it's placed upon).
If you are using the Session variable just to get a variable reactive (meaning trigger an autorun), you should use getReactively . this just returns the already existing scope variable but trigger an autorun every time it changes. a good example of this can be found it our tutorial.
Note: In anyway, when you use Tracker.autorun inside Angular, you need to connect it to a scope. this can be easily done if you replace Tracker.autorun with the $meteorUtils autorun function
Would be great if you could share a repo so that I can look on the broader perspective and could better determine what's the best solution from the two.
Based on another answer about "session" reacitivity, I could solve the problem. Just use the approach described in the link https://stackoverflow.com/a/21046935/4035797. You have to substitute Deps.autorun by Tracker.autorun though as Deps is deprecated and you have to make the scope variables for use in the template reactive (e.g., $scope.sentence_type = Session.getJSON("current_sentence.sentence_type");) and not the tokenizer.
I have one variable say var tree.I want to use this variable in two files say a.js and b.js.Both files changes state of variable tree.I want to access that variable in other files with change state.How it is possible??
There are more elegant ways of doing it, as described in the question linked in the comments, but the simplest way is to define a RequireJS module with an object literal to hold the shared state:
define('sharedstuff', [], {tree: "original value"});
And then from other module you can require it:
require(['sharedstuff'], function(sharedstuff) {
sharedstuff.tree = "new value";
};
And if from yet another module you require it, RequireJS will not reload a fresh copy but will instead give you the already loaded version with your shared value populated:
require(['sharedstuff'], function(sharedstuff) {
console.log(sharedstuff.tree) // should be "new value"
};