Meteor - Trying to return a built URL in a helper, coming back blank? - meteor

I'm trying to return a URL that I build up in a helper and add it to my href, but its coming back blank. I'm console.logging my final URL and its correct. I"ve tried single quotes, double and tripple {{{myhelper}}}. But it returns blank and removes the HREF attribute altogether???
my .html within a loop, passes the row.
<td class="table__cell">
<a href={{ buildUCDLink row }} >go</a>
</td>
my .js helper
buildUCDLink(process){
const thisTemplate = Template.instance();
const integrations = thisTemplate.integrations.get();
integrations.forEach((integration) => {
if (integration._id._str === process.integration_id._str ) {
const finalUcdUrl = integration.ucd_url + '/#applicationProcessRequest/' + process.id;
console.log('finalUcdUrl: ', finalUcdUrl);
return finalUcdUrl;
}
});
},

That is not so easy to follow but if you are trying to trigger it from an anchor. I think you would want to run it like this:
<a href="javascript:void(0);" onclick="buildUCDLink(row);">
Which I think is long hand for:
<a href="javascript:buildUCDLink(row);">
If I am wrong, please let me know a bit more about what you are trying to do here.

for some reason I needed to reassign the var outside the loop. This worked:
buildUCDLink(process){
const thisTemplate = Template.instance();
const integrations = thisTemplate.integrations.get();
let returnURL = '';
integrations.forEach((integration) => {
if (integration._id._str === process.integration_id._str ) {
const finalUcdUrl = integration.ucd_url + '/#applicationProcessRequest/' + process.id;
returnURL = finalUcdUrl;
}
});
return returnURL;
},

Related

GoogleDocs API logic and programming

I want to use a logic in my GoogleDocs Template for Zapier. I just want to do something like
{{if strstr(name, “google”)}} hello
{{/if}}
Is that possible or can I just use placeholders like {{name}}?
For something that basic, you could capture the original text, use mustache to apply the logic and then rely on the replaceText merge method recommended in the api docs.
let requests = [];
let contents = doc.body.content||[];
contents.reverse().forEach(content=>{
const paragraph = content.paragraph||{};
const elements = paragraph.elements||[];
const paragraphContent = elements.reduce((acc, obj)=> { return [...acc, obj.textRun.content]}, []);
var parts = paragraphContent.join('').match(/{{#(.*?)}}(.*?){{\/(.*?)}}/g)||[];
parts.forEach((part, index)=>{
requests.push({
replaceAllText: {
containsText: {
text: part,
matchCase: true,
},
replaceText: mustache.render(part, objMerge)||'',
},
})
})
})

Use setState to change the value of a grandchild object

Everything I have tried from what I can find doesn't seem to be working. I'm really curious how to access and edit grandchild objects located in the state with react. If anyone could tell me what I'm doing wrong, it would be very helpful.
https://codesandbox.io/s/0mo32q85pp
Take a look at the following code...
App.js
lines: 41-58
getHomeworld = URL => {
fetch(URL)
.then(res => {
return res.json();
})
.then(homeWorldObject => {
console.log(homeWorldObject);
// this.setState({ <- Why isn't this working????
// ...this.state.starwarsChars,
// ...this.state.nextPage,
// ...this.state.prevPage,
// ...this.state.starwarsChars.homeworld = homeWorldObject
// });
})
.catch(err => {
throw new Error(err);
});
};
lines: 86-89
<CharacterList
characters={this.state.starwarsChars}
getHomeworld={this.getHomeworld}
/>
CharacterList.js
lines: 8-12
<Character
key={character.name}
characterDetails={character}
getHomeworld={props.getHomeworld}
/>
Character.js
lines: 18-29
{Object.keys(props.characterDetails).includes("homeworld") ? (
<div className="character-homeworld">
<Homeworld
homeworld={props.getHomeworld(props.characterDetails.homeworld)}
/>
</div>
) : (
<div className="character-homeworld">
<h4>Homeworld</h4>
<p>None</p>
</div>
)}
Homeworld.js
lines: 7-10
<div className="homeworld-details">
<p>Name: {props.name}</p>
<p>Rotation Period: {props.rotation_period}</p>
</div>
Expected Output:
If you look on the sandbox webpage, the "Name" and "Rotation Period" (Under "Homeworld") should display the values from here: https://swapi.co/api/planets/1/
Is there anyone who can help me figure this out?
EDIT:
I got really close making these changes (using my local machine, the code on the sandbox is still the original)...
App.js
let temp = {...this.state.starwarsChars} // use spread operator to clone it, so you don't mutate state on next line;
for (let character in temp) {
if (temp[character].homeworld === URL) {
temp[character].homeworld = homeWorldObject;
}
}
// console.log(temp);
this.setState({
starwarsChars: temp
});
Character.js
const Character = props => {
props.getHomeworld(props.characterDetails.homeworld);
console.log(props.characterDetails); // returns object{homeworld: {object}}
console.log(props.characterDetails.homeworld); // returns url
and...
<div className="character-homeworld">
<Homeworld
homeworld={props.characterDetails.homeworld}/>
</div>
However, the issue now is if I do console.log(props.characterDetails.homeworld);, it logs homeworld: url
and...
if I do console.log(props.characterDetails);, it logs the property of the character object as homeworld: {object}
...
What I want is the 2nd one, and I'm not sure why it's not consistent.
Update
For some strange reason, codesandbox is console logging both urls, and when I run with yarn start, it logs the url for one, and the object for another. Because of this... I am adding the github link here -> https://github.com/jamespagedev/Sprint-Challenge-React-Wars (so the error can properly be reproduced)
Edit 2:
I changed the sandbox code to the following so we are now only worrying about the code in 1 file -> https://codesandbox.io/s/0mo32q85pp
Here is the issue I am now seeing, and I'm not sure how to solve it...
getHomeworld = URL => {
let home;
fetch(URL)
.then(res => res.json())
.then(homeWorldObject => {
home = homeWorldObject;
console.log(home); // home is an object
});
console.log(home); // why is home undefined?
return home;
};
I've tried doing return homeWorldObject, but the main function just returns undefined. After doing the console logging, that was what I found, and I'm not sure why that is happening...

Meteor Helper using query based on reactive variable

I'm trying to use a helper that should return a Collection specifying a subset of the whole Collection with $in using a reactive array from templates:array.
I have
var tags = new ReactiveArray();
and on some event I change the contents of the array, something along the lines of
tags.pushArray(note.tags);
(or maybe I should use .set()?)
My helper is
Template.editor.helpers({
tagslist() {
return Tags.find({ _id: { $in : tags }});
},
});
But then I get an exception in meteor.js:1010 which looks like this
if (allArgumentsOfTypeString)
console.log.apply(console, [Array.prototype.join.call(arguments, " ")]);
In the stack there is compileValueSelector. This seems to indicate that the compilation of the helper is not content with what it finds.
I've also tried to make tags a template local instance, and adding .get() to the tags in the helper query. But with the same result.
Where should I start looking? Am I using ReactiveArray correctly? Is it possible to do what I want, namely have a reactive query based on an ReactiveArray?
I personally have not used ReactiveArray but I assume this same pattern would work. I stick to using ReactiveVar so here is an example that should get you going in the right direction.
Template.editor.onCreated(function () {
const instance = this;
instance.tags = new ReactiveVar([]);
});
Template.editor.helpers({
tagslist() {
const tags = Template.instance().tags.get();
return Tags.find({ _id: { $in : tags }});
}
});
Template.editor.events({
'click .tag'(event, instance){
const tag = this;
const tags = instance.tags.get();
tags.push(tag);
instance.tags.set(tags);
}
});

how to handle onclick = getRedirectPage(34342,55,46) using Jsoup?

I am doing a school project that need to use jsoup to scrape some datas from certain website.
I saw a button as following attribute:
<a rel="nofollow"
onclick="getRedirectPage(37443499,2206,801)"
class="showtime_btn btn btn-default seat_3"
id="37443499"
href="javascript:void(0)" role="button">06:40PM
<br>
<small>IMAX 3D</small
></a>
//below is the getRedirect method. I was trying to understand it,
but I dont know what language they using, have no idea where to learn the necessary knowledge to understand it, please help me out.
thank you !!
var timeout = "";
function clickRedirect(){
ga('send', 'event', 'Redirect_CTA', 'click', viewModel.popupRedirectAdsEventName());
}
function getRedirectPage(shid, movieid, cinemaid){
$('#page-overlay').show();
ga('send', 'event', 'Movie_SelectShowtime', 'click_showtime', movieid, cinemaid);
$.get("https://www.popcorn.app/sg/showtime/redirect",
{
showtimeid: shid
},
function (data){
setTimeout(function(){
$('#page-overlay').fadeOut();
},100);
var dt = JSON.parse(data);
if(dt.status > 0){
dt = dt.data;
viewModel.popupRedirectToLang(dt.lang_redirectto.replace('%s', dt.site));
viewModel.popupDisclaimer(dt.lang_disclaimer);
if(dt.redirect_ads != undefined && dt.redirect_ads.event_name != undefined){
viewModel.isExternalTraffic(true);
viewModel.popupRedirectAdsUrl(dt.redirect_ads.url);
viewModel.popupRedirectAdsLabel(dt.redirect_ads.label);
viewModel.popupRedirectAdsEventName(dt.redirect_ads.event_name);
}else{
viewModel.isExternalTraffic(false);
}
viewModel.popupRedirectNote(dt.lang_redirectnote);
viewModel.popupFollowUrl(dt.follow);
viewModel.popupLangBtn(dt.lang_btn_txt);
viewModel.targetBlank("_blank");
//campaign:
if(dt.campaigns != undefined && dt.campaigns.trackingUrl != undefined){
viewModel.isCampaignValid(true);
viewModel.adImage(dt.campaigns.adImage);
viewModel.campaignName(dt.campaigns.campaignName);
viewModel.isSmallerFont(dt.campaigns.isSmallerFont);
viewModel.campaignPercentage(dt.campaigns.campaignPercentage);
viewModel.companyName(dt.campaigns.companyName);
viewModel.campaignAddress(dt.campaigns.campaignAddress);
viewModel.campaignTrackingUrl(dt.campaigns.trackingUrl);
viewModel.discountedPrice(dt.campaigns.discountedPrice);
viewModel.originalPrice(dt.campaigns.originalPrice);
}else{
viewModel.isCampaignValid(false);
}
$("#redirectPopupTarget").show();
$(".close_btn").click(function(){
clearTimeout(timeout);
$("#redirectPopupTarget").hide();
});
timeout = setTimeout(function(){
window.location.href = dt.follow;
},5000);
}
})
.error(function (er) {
console.log("Error:", er.responseText);
});
}
$(document).ready(function(){
$("#redirectPopupTarget").css('height', $(window).height());
});
enter image description here
below link is the id = redirectPopupTarget
This is javascript with jQuery. This code does some other things, but I think you are most interested in getting redirect link.
This is done by sending request to https://www.popcorn.app/sg/showtime/redirect?showtimeid=shid. Where shid is first parameter of you javascript function (https://www.popcorn.app/sg/showtime/redirect?showtimeid=37443499).
The response to this request is in form of JSON and element you are looking for is in the field follow

Meteor: Access Template Helper (or variable) from another helper

How can I reference a template helper from another one? For example...
Template.XXX.helpers({
reusableHelper: function() {
return this.field1 * 25 / 100; //or some other result
},
anotherHelper: function() {
if (this.reusableHelper() > 300) //this does not work
return this.reusableHelper() + ' is greater than 300';
else
return this.reusableHelper() + ' is smaller than 300';
}
});
I have also tried Template.instance().__helpers.reusableHelper - all with no luck.
Alternatively is there a way to define reactive Template instance variables?
XXX is a sub-template that renders multiple times on the same page.
You can but only with global template helpers.
Blaze._globalHelpers.nameOfHelper()
Here is an example calling Iron:Router's pathFor global helper.
Template.ionItem.helpers({
url: function () {
var hash = {};
hash.route = path;
hash.query = this.query;
hash.hash = this.hash;
hash.data = this.data;
var options = new Spacebars.kw(hash);
if (this.url){
return Blaze._globalHelpers.urlFor(options)
} else if( this.path || this.route ) {
return Blaze._globalHelpers.pathFor(options)
}
}
});
EDIT: To your second question. You can call the same template as many times as you like on a page and pass different data attributes directly into it and/or use #each block template wrapper to iterate over data. #each will call a template many times giving it a different data context each time.
#each Example
<template name="listOfPosts">
<ul>
{{#each posts}}
{{>postListItem}} <!--this template will get a different data context each time-->
{{/each}}
</ul>
</template>
Attributes Example
<template name="postDetails">
{{>postHeader title="Hello World" headerType="main" data=someHelper}}
{{>postHeader title="I am a sub" headerType="sub" data=newHelper}}
{{>postBody doc=bodyHelper}}
</template>
This like using of common code, you can make another javascript function which contains the your reusable code and call it from wherever you required.
Like in your code-
function calcField(field){
return field * 25 / 100
}
and in you template helper-
Template.XXX.helpers({
reusableHelper: function() {
return calcField(this.field1);
},
anotherHelper: function() {
if (calcField(this.field1) > 300)
return calcField(this.field1) + ' is greater than 300';
else
return calcField(this.field1) + ' is smaller than 300';
}
});
and
Alternatively is there a way to define reactive Template instance
variables?
you can use Session variables or Reactive variable
Disclaimer: This may not answer your question directly, but it might be helpful for people stuck with a similar use case:
Sometimes it's easy to get locked into the "Meteor way", that standard Javascript rules are forgotten.
Two use cases that sound similar to what you're trying to do:
1. For helpers/events that you can access anywhere on the client-side, simply set a global helper.
Put this in, say, client/helpers.js:
Helpers = {
someFunction: function(params) {
/* Do something here */
}
}
Now Helpers.someFunction() is available to all templates.
If you want to bind the local template instance to it for some reason, again, it's standard JS:
var boundFunction = Helpers.someFunction.bind(this);
2. To create reusable Blaze helpers inside of templates, use Template.registerHelper
For example, this function uses the "numeral" library to format numbers:
Template.registerHelper('numeral', function(context, opt) {
var format = (opt.hash && opt.hash.format) || '0,0.00';
return numeral(context || 0).format(format);
});
You can use this in any template like so:
{{numeral someNumberVariable format='0,0'}}
I found a better solution with collection hooks:
Item = new Mongo.Collection('Items');
Item.helpers({
isAuthor: function(){
return this.authorId == Meteor.userId();
},
color: function(){
if(this.isAuthor())
return 'green';
else
return 'red';
}
});
I then becomes functions of this, usable in both helpers and templates.
i had something similar -- i had 2 helpers in the same template that needed access to the same function. however, that function 1) needed access to a reactive var in the template, and 2) is a filter function, so i couldn't just pass in the data of that reactive var.
i ended up defining the filter function in the templates onCreated() and stored it in a reactive var, so the helpers could access it.
Template.Foo.onCreated(function () {
this.fooData = new ReactiveVar();
function filterFoo(key) {
var foo = Template.instance().fooData.get();
// filter result is based on the key and the foo data
return [true|false];
}
this.filterFoo = new ReactiveVar(filterFoo);
});
Template.Foo.helpers({
helper1: function() {
var filterFn = Template.instance().filterFoo.get();
return CollectionA.getKeys().filter(filterFn);
},
helper2: function() {
var filterFn = Template.instance().filterFoo.get();
return CollectionB.getKeys().filter(filterFn);
},
});
Since this answer is currently missing - I wanted to add an update
In the current meteor version, you should be able to call:
var TEMPLATE_NAME = //the name of your template...
var HELPER_NAME = //the name of your helper...
Template[TEMPLATE_NAME].__helpers[' '+HELPER_NAME]
You should call it like this, if you want to make sure the helper has access to this:
var context = this;
Template[TEMPLATE_NAME].__helpers[' '+HELPER_NAME].call(context,/* args */);
But be careful - this could break in future Meteor versions.
Adding on to Nils' answer, I have been able to access Template level helpers in events using the following code:
'click a#back': (event, instance) ->
if instance.view.template.__helpers[' complete']() && instance.view.template.__helpers[' changed']()
event.preventDefault()
this just came up again at work, and this time we used modules. in this case, we had a number of large, related functions that had to maintain data across calls. i wanted them outside the template file but not totally polluting the Meteor scope. so we made a module (polluting the Meteor scope 1x) and called the functions therein from the template.
lib/FooHelpers.js:
FooHelpers = (function () {
var _foo;
function setupFoo(value) {
_foo = value;
}
function getFoo() {
return _foo;
}
function incFoo() {
_foo++;
}
return {
setupFoo: setupFoo,
getFoo: getFoo,
incFoo: incFoo
}
})();
FooTemplate.js:
Template.FooTemplate.helpers({
testFoo: function() {
FooHelpers.setupFoo(7);
console.log(FooHelpers.getFoo());
FooHelpers.incFoo();
console.log(FooHelpers.getFoo());
}
});
console output is 7, 8.

Resources