After passing object to handlebars, how can I access that object in script tag? - node.js

I first get the data from sql then pass it into handlebars.
Inside the tag in .handlebars/using view.js, I want to access doctors, but i keep getting[object][object]. I tried json.stringifying it before but still no luck. What is the best way to do this?
umd.matchDocs(val2, function(data) {
console.log(data);
var renderDocs = {
doctors: data
}
res.render("dashboard", renderDocs);
});

After passing object to handlebars, how can I access that object in script tag?
No, not by default. But you can make the data available manually if you want.
Data you pass to handlebars rendering operation is available during the rendering operation only. If you want to be able to access some of that data later in client-side <script> tags, then you can "render" Javascript variables into the <script> tags that contain the desired data.
Remember when rendering data into Javascript variables, you need to render the actual Javascript text (converting to JSON will often create the text for you).
In your specific example, you could do something like this in your rendering code:
umd.matchDocs(val2, function(data) {
console.log(data);
var renderDocs = {
doctors: JSON.stringify(data)
}
res.render("dashboard", renderDocs);
});
And, then in the template:
<script>
var doctors = {{{doctors}}};
</script>
Then, this array of doctors would be available to the Javascript in your page.
In case you haven't seen the triple braces like shown above, that's to tell handlebars to skip any HTML escaping in the data (because this isn't HTML).

Related

Variable Scope in ejs/express

So I am trying to sort out variable scope. Below is a simple snippet of code:
const params = {
versions: versions,
user: user,
statsParams: statsParams,
csrfToken: csurf.createToken(req),
};
res.render("server/edit", params);
return;
Now the values that are in the params object are available in the ejs page for use. What I am seeing is that other variables that precede this code block also seem to be available in the ejs file as well not just the ones passed via the param object. Is this expected behavior? I have looked on the ejs website and it doesn't speak of variable scope.
Brad
What you are doing with your code is rendering the page using ejs and passing the params object to the page. By passing it to the page you can render the page with access to the variables you passed in using the following tags : <%= variable =>
In terms of scope, you have now rendered the page to have access to all the variables you have passed in under the name params during the operation : res.render("server/edit", params);
If you have passed other variables through api calls to your backend you will also be able to access them in their according scope, but unless you include other variables to be passed as parameters you will not be able to access other variables from your backend.
Example :
--> userController.js
var outOfScope = True;
const params = {
versions: versions,
user: user,
statsParams: statsParams,
csrfToken: csurf.createToken(req),
};
res.render("index", params);
return;
--> index.html
...
<h1>Variable</h1>
<p><%= params.user %></p>
...
This will not work
...
<h1>Variable</h1>
<p><%= outOfScope %></p>
...
If you still have issues regarding access to variables you haven't passed it is possible you may have included them from another file by accident (ex. a header that is included).
I hope this helps, but if you are having trouble with specific variables please include them in your question as well as how you are accessing them.

change the expression in lwc component while iterating

We can use variables in aura components to concatenate some expression, we have to use variable name itself in lwc components, while looping how to change the lwc comp variable in js file.
I tried to access the dom using this.template.querySelector(); but this one is only giving the value if I use a rendered callback.
<template for:each={documentLinks} for:item="item">
//here I need to pass the item.ContentDocument.LatestPublishedVersionId to the end of a URL string
<img src={item.srcUrl} alt="PDF"/>
we can modify the returned data from apex but the data is proxy we cannot modify it.
One of the possible solutions to change the URL on the dom when it loads is to change the returned data from the server. here, In lightning web components the returned data is a proxy object, only readable. so we have to clone it(there are multiple ways to clone it), to make any changes. but here what I did.
therefore, overrides array is going to be the new data.
let overrides = [];
let newData = {
contentDocs: data[i],
srcUrl: '/sfc/servlet.shepherd/version/renditionDownloadrendition=thumb120by90&versionId=' + data[i]['ContentDocument']['LatestPublishedVersionId']
};
makeLoggable(newData);
overrides.push(newData);
function makeLoggable(target) {
return new Proxy(target, {
get(target, property) {
return target[property];
},
set(target, property, value) {
Reflect.set(target, property, value);
},
});
}

Passing JavaScript variable into snippet

I'm working on a search form for my ModX application that is consisted of a chunk and a snippet. What I'm trying to achieve is to pass what was entered into the search box into a javascript variable and then pass it to my snippet, however, the snippet receives the literal text, and not the value that I enter into the parameter when I call it.
I don't know if what I'm attempting is possible in ModX or if I need to take a different approach, but I would be hugely thankful for anyone who can provide any insight.
Chunk:
<script>
$('.search-btn').click(function() {
var search = $('.search-entry').val();
[[showSearchResults? &q=`search`]]
});
</script>
Snippet:
<?php
$search = $modx->getOption('q', $scriptProperties);
echo $search; // this always prints "search"
?>
I doubt that this code makes sense:
<script>
$('.search-btn').click(function() {
var search = $('.search-entry').val();
[[showSearchResults? &q=`search`]]
});
</script>
The snippet call returns the result of snippet's execution with param q always equal to the string 'search' in your case and finally on your page you will have something like this:
<script>
$('.search-btn').click(function() {
var search = $('.search-entry').val();
'search' // assuming your snippet just returns what has been passed to it.
});
</script>
In order to accomplish your task you can use a simple trick. Call your snippet like this:
[[!yourSnippet? &yourVar=`[[!#POST.yourVar]]` ]] // or GET
Lets say this snippet call is located on a page accessible via url /test/ on your server. So, now you just have to send the parameters you collected from your search form using AJAX to the /test/ page where your snippet is:
var yourVar = $('.search-entry').val();
$.ajax({
type: "POST",
url: "/test/",
data: {yourVar: yourVar},
success: success,
dataType: "html"
});
Hope it helps :)
PS If you want to search Resource content and TV content, I can highly recommend an extra called SimpleSearch.

How to send some data of one template to another template Meteor

I want to share some data from template to another template using Meteor. I have a template i.e allInventory.html on which i am showing some data in table form i added three links there that is. one for view , edit and delete what i want iam getting all the data from backend into one of helper i.e productDetails and i bind an event with view button that will take the data of current user clicked on which product so i have successfully getting the data at my allinventory template but there is another template i.e productDetails on which i want to render or show that data. But stuck with that i have data on allInventory click event but not know how do ishare the same with productDetails template.
Here is my allInventory.js
Template.allInventory.rendered = function() {
Template.allInventory.events({
"click .btn":function (e){
data = $(e.target).attr('data');
Router.go('productDetail', {data: $(e.target).attr('data')}, {query: 'q=s', hash: 'hashFrag'});
console.log("button clicked.."+data);
console.log(data);
}
})
ProductDetails.js
Template.productDetail.rendered = function () {
Template.productDetail.helpers({
productDetails: function() {
return data;
}
});
allInvenrtory.html
<button type="button" data ="{{productInfo}}" class="btn btn-info btn-sm"><i class="fa fa-eye"></i>View</button>
I just simply want to share allInventory template data with productsDetails template.
Any help would be appriciated!
Thanks
I'd recommend avoiding Session for this purpose, since it is a global object, but more importantly, because there are better ways to do it.
You can pass data from the parent templates to the child template using helpers: https://guide.meteor.com/blaze.html#passing-template-content
You can pass data from the child to the parent templates using callbacks https://guide.meteor.com/blaze.html#pass-callbacks
I'd structure this app to have a container (page) template, which will have all the subscriptions and render one of your templates based on the URL.
You can use the Session variable if you want to share data between templates.
You can follow this guide:
http://meteortips.com/first-meteor-tutorial/sessions/
I would put both template in a third, parent template.
ParentTemplate
-SharedInfo
-KidTemplate1
-KidTemplate2
Then having this third template hold the information you want to share across templates.
For that you can use a ReactiveVar, ensuring that change by template1 code on the parent template is visible in template2 as well.
To access the parent template for the kids, you can do something along those lines :
Blaze.TemplateInstance.prototype.parentTemplate = function (levels) {
var view = Blaze.currentView;
if (typeof levels === "undefined") {
levels = 1;
}
while (view) {
if (view.name.substring(0, 9) === "Template." && !(levels--)) {
return view.templateInstance();
}
view = view.parentView;
}
};

How to use Node.js to create modified versions of html documents?

I am trying to do this:
Read html document "myDocument.html" with Node
Insert contents of another html document named "foo.html" immediately after the open body tag of myDocument.html.
Insert contents of yet another html document named "bar.html" immediately before the close body tag of myDocument.html.
Save the modified version of "myDocument.html".
To do the above, I would need to search the DOM with Node to find the open and closing body tags.
How can this be done?
Very simply, you can use the native Filesystem module that comes with Node.JS. (var fs = require("fs")). This allows you to read and convert the HTML to a string, perform string replace functions, and finally save the file again by rewriting it.
The advantage is that this solution is completely native, and requires no external libraries. It is also completely faithful to the original HTML file.
//Starts reading the file and converts to string.
fs.readFile('myDocument.html', function (err, myDocData) {
fs.readFile('foo.html', function (err, fooData) { //reads foo file
myDocData.replace(/\<body\>/, "<body>" + fooData); //adds foo file to HTML
fs.readFile('bar.html', function (err, barData) { //reads bar file
myDocData.replace(/\<\/body\>/, barData + "</body>"); //adds bar file to HTML
fs.writeFile('myDocumentNew.html', myDocData, function (err) {}); //writes new file.
});
});
});
In a simple but not accurate way, you can do this:
str = str.replace(/(<body.*?>)/i, "$1"+read('foo.html'));
str = str.replace(/(<\/body>)/i, read('bar.html')+'$1');
It will not work if the myDocument content contains multiple "<body ..' or '</body>', e.g. in javascript, and also the foo.html and bar.html can not contains '$1' or '$2'...
If you can edit the content of myDocument, then you can leave some "placeholder" there(as html comments), like
<!--foo.html-->
Then, it's easy, just replace this "placeholder" .
Use the cheerio library, which has a simplified jQuery-ish API.
var cheerio = require('cheerio');
var dom = cheerio(myDocumentHTMLString);
dom('body').prepend(fooHTMLString);
dom('body').append(barHTMLString);
var finalHTML = dom.html();
And just to be clear since the legions of pro-regex individuals are already appearing in droves, yes you need a real parser. No you cannot use a regular expression. Read Stackoverflow lead developer Jeff Atwood's post on parsing HTML the Cthulhu way.

Resources