The below is an excerpt from the controller for the page I am loading (in coffeescript - but should be straightforward to read). Once I have data from the server, I transform it into a json array of arrays. onChartDataReady then runs, loads 3 files via the jsapi all with http status 200, but onGoogleReady is never called.
onDataLoad: (data) =>
# #$scope.chartData = transformed data
#onChartDataReady()
onChartDataReady: =>
google.load 'visualization', '1', { packages: ['corechart'] }
google.setOnLoadCallback #onGoogleReady
onGoogleReady: =>
chartTable = google.visualization.arrayToDataTable #$scope.chartData
chartOptions = { title: 'Some silly data' }
chart = new google.visualization.LineChart document.getElementById('chart_div')
chart.draw chartTable, chartOptions
I copied the quickstart code from google and pasted that into a html file with no controller (i.e. angular is just loading the html) but it has the same problem - callback is not called. When I open the file from my desktop it works fine. Somehow angular is interfering with the google callback and I do not know how to troubleshoot.
Any pointers would be very helpful! Thanks.
This might be related to an odd behavior in the google loader. Try passing the callback inline with the google.load call instead of calling google.setOnLoadCallback. The javascript would look like this:
google.load('visualization', '1', { packages: ['corechart'], callback: <callback function> });
I'm not a coffescript expert, but I think this is the syntax you would use:
google.load 'visualization', '1', { packages: ['corechart'], callback: #onGoogleReady }
Related
In my project I'm using React-Dropzone-Component (https://github.com/felixrieseberg/React-Dropzone-Component) based on Dropzone.js.
I'm using this component because I'm developing a SharePoint webpart and there is already an example based on this solution on Microsoft PnP GitHub repository.
Anyway, the upload is working fine, but sometimes, mainly when I keep a web page opened for a couple of minutes doing nothing, I receive an error trying to upload new files. I retry an upload and it fails returning Server responded with (0) code error. I also see on Google Chrome console an ERR_CONNECTION_RESET error. If I try to upload 5 files in second instance, I get error on first 2-3 and then the remaining files works fine. Weird.
I've already investigated my network, but there are no failures. I've also tried with 3 different networks and I've received the same error.
I've also updated the component with the latest Dropzone.js (5.7.2).
This is my code:
let componentConfig = {
iconFiletypes: this.props.fileTypes.split(','),
showFiletypeIcon: true,
postUrl: _context.pageContext.web.absoluteUrl,
autoProcessQueue: true
};
var djsConfig = {
headers: {
"X-RequestDigest": digest1
},
addRemoveLinks:false
};
let myDropzone;
let eventHandlers = {
// This one receives the dropzone object as the first parameter
// and can be used to additional work with the dropzone.js
// object
init: function(dz){
myDropzone=dz;
},
sending: async function (file, xhr) {
var fileName = file.name;
fileName = fileName.replace(/[&\/\\#,+()$~%='":*?<>{}]/g, "");
if (file.size <= 10485760) {
// small upload
await web.getFolderByServerRelativeUrl("/test/"+_listName).files.add(fileName, file, true).then(_ => console.log("Ok!"));
} else {
// large upload
await web.getFolderByServerRelativeUrl("/test/"+_listName).files.addChunked(fileName, file, data => {}, true).then(_ => console.log("Ok!"));
}
},
error:function(file,error,xhr){
file.status = myDropzone.ADDED;
myDropzone.removeFile(file);
myDropzone.enqueueFile(file);
}
};
<DropzoneComponent eventHandlers={eventHandlers} djsConfig={djsConfig} config={componentConfig}>
<div className="dz-message icon ion-upload">Drop files here to upload</div>
</DropzoneComponent>
If I can't prevent this ERR_CONNECTION_RESET error, I would like to set up an automatic retry for these files. The code I've posted above is not working fine or it returns "Uncaught Error: This file can't be queued because it has already been processed or was rejected.".
Is there a solution or a good way to set up a retry?
I've created a .NET Core Web API that uses SPA with React. I want to preload some data into the application.
My startup.cs file looks like this:
app.UseSpa(spa => {
spa.Options.SourcePath = "ClientApp";
spa.UseSpaPrerendering(options => {
options.BootModulePath = $"main.chunk.js";
options.SupplyData = (context, data) => {
data["siteConfiguration"] = "{my custom object}";
};
});
if (env.IsDevelopment()) {
spa.UseReactDevelopmentServer(npmScript: "start");
}
});
I'm getting an error about the BootModulePath is not being found.
Couldn't find any information about this property used with React or how to pre-render data into React SPA with .NET Core.
Is there an example on how to accomplish this?
Thanks
I'm using a bit of a different approach to accomplish this. I am using spa services in .net core https://learn.microsoft.com/en-us/aspnet/core/client-side/spa-services?view=aspnetcore-2.2#server-prerendering to do my pre rendering. I am also using razor pages to generate the html page (with just a single div for react to mount to). All I need to do is add a tag on my root div in my Index.cshtml page that looks something like this:
<div id="react-app" asp-prerender-module="ClientApp/dist/main-server">Loading...</div>
The entry point for my main-server bundle looks like:
export default createServerRenderer(params => {
//do stuff here
return new Promise<RenderResult>((resolve, reject) => {
params.domainTasks.then(() => {
resolve({
html: /* html string rendered by your app */,
globals: {
cachedVar1: data1,
cachedVar2: data2
}
});
}, reject); // Also propagate any errors back into the host application
});
});
This lets me pre-load data that was created by node during the pre-rendering by putting them in global variables in JavaScript.
If you want to pre-load data that comes from the .net core server and not from node, then what you can do is to pass that data as part of your model to the view.
public async Task<IActionResult> Index()
{
//get data here
return View(preloadedData);
}
Then in the Index.cshtml page, you can add something like this:
<script>
var PRELOADED_CACHE = #Html.Raw(Json.Serialize(#Model));
</script>
This will put a global variable called PRELOADED_CACHE which you can access from your application in the browser (but won't be available during pre-rendering).
I know this isn't precisely what you are looking for, but hopefully this at least gives you some helpful ideas.
Let's say I have the following method
public function prepareEmail($dataModel)
{
return $this->container->get('templating')->render(
'MyBundle:Emails:email-document.html.twig',
[
'data' => $dataModel,
]
)
}
I want to test a very complicated logic that I have in my twig template.
In my phpunit test kit I'm not mocking TwigEngine service so I'm working with a fully rendered templates.
In my test I doing something like this
public function testPrepareEmail()
{
$template = $this->manager->prepareEmail($testData);
static::assertContains('some part of template', $template);
}
Everything looks good, but I'm added the following string to one of my templates
{{ app.request.getSchemeAndHttpHost() }}
And now I'm getting error
Twig_Error_Runtime : Impossible to invoke a method ("getSchemeAndHttpHost") on a null variable.
which is very reasonable, the question is how to mock Symfony Request object in my case?
I have a comments widget, in React js (jsx), and I'm using React Dropzone and uploading the dropped files to the server, using superagent.
I need to get the file object (containing my app's file id,etc) returned from my app, and associate them with the comment that the user will submit. I am attempting to assign the file objects to a state variable, 'attachments'. Because of the async nature of superagent, I think, I am actually populating my state variable with an empty array.
I have tried to use a callback, but got an 'undefined' error.
Here is the code:
onDrop: function (newFiles) {
newFiles.forEach((file)=>
{
this.setState({files: this.state.files.concat(file)});
})
var attachments = [];
var req = request.post('/attachments/create');
req.set('Accept', 'application/json');
newFiles.forEach((file)=> {
req.attach('img_attach', file);
req.field('filename', file.name);
req.field('itemType', 'comment');
req.field('itemId', false);
req.end(function(err,res){
var json = $.parseJSON(res.text);
attachments.push(json);
attIds.push(json.id);
});
});
attachments.forEach((file)=>
{
this.setState({
attachments:this.state.attachments.concat([file])});
});
},
Here is the callback attempt which returns "Cannot read property 'setState' of undefined":
function fileAttach(err,res)
{
var json = $.parseJSON(res.text);
this.setState({attachments:this.state.attachments.concat([json])});
}
For the callback, instead of this
req.end(function(err,res){
var json = $.parseJSON(res.text);
attachments.push(json);
attIds.push(json.id);
});
I use this
req.end(fileAttach);
So, one possibility is that I'm looking for a 'context' option, similar to jquery, that allows me to use 'this' in the callback.
So, you were on the right track for the first issue I see. You need to bind the context to that function. It's already been answered by LodeRunner28 in the comments, but you'd do:
req.end(fileAttach.bind(this))
If you're not familiar, Function.prototype.bind allows you to manually force a context variable for any function. It's incredibly handy, and it means you never have to rely on the library (eg. jQuery) to provide a context arg, you can just specify it yourself :)
The bigger issue I see is the way you're using SuperAgent. I believe you're actually sending a whole bunch of requests; calling .end triggers SuperAgent to make the request, and you're doing it inside the forEach loop.
I'm not super familiar with SuperAgent, but I believe you can just do:
newFiles.forEach( file => {
req.attach('img_attach', file);
req.field('filename', file.name);
req.field('itemType', 'comment');
req.field('itemId', false);
});
req.end(fileAttach.bind(this));
I've got a custom module I'm creating called touchpoints. At the top of the touchpoints.module file I have the following:
global $base_path;
$my_settings = array(
'basepath' => $base_path,
'module_path' => drupal_get_path('module','touchpoints')
);
drupal_add_js(array('touchpoints' => $my_settings), 'setting');
drupal_add_js(drupal_get_path('module','touchpoints') . '/touchpoints.js');
Then in my touchpoints.js file I have the following:
Drupal.behaviors.touchpoints = function(context){
$('.form-item-touchpointlocation').css('display','block');
$('.form-item-touchpointcategory').css('display','none');
}
It's my understanding that anything inside the Drupal.behaviors call should run when the DOM finishes loading similar to a $(document).ready call. However, this code isn't being executed. Just to be sure I put an alert in the function as well, and it wasn't being triggered. Is there a step I'm missing?
I realized I was using Drupal 6 syntax. In Drupal 7 you have to declare behaviors differently. It should have looked like this
(function ($) {
Drupal.behaviors.touchpoints = {
attach: function (context, settings) {
$('.form-item-touchpointlocation').css('display','block');
$('.form-item-touchpointcategory').css('display','none');
}
};
})(jQuery);
For reference see: http://drupal.org/node/756722