I am new to Ember and in my APP I need to add some operations depending on the JSON I get from the server.
This is currently my logic:
In the component.js
var foo = [];
didInsertElement() {
var data = this.get('content');
//then I do some transformations with data to obtain what I want and assign it to foo
data.forEach(function(option) {
list.push( JSON.parse(JSON.stringify(option)))
})
for(i = 0; i < list.length; i++) {
//some logic code with list
}
this.set('foo', someTransformationFromList);
for (i = 0; i < count; i++) {
this.get('content').push(jQuery.extend(true, {}, this.get('content')[0]));
}
for(i = 0; i < foo.length; i++) {
this.get('content')[i].set('string1', foo[i].text);
this.get('content')[i].set('id', foo[i].value);
}
}
So now the question is, I need to move this logic from didInsertElement to somewhere else so it gets executed every time I get my JSON no just the first time when the component is rendered. I have tried to use a serializer or a transform but I don't know if I can use any of them. Can you please give me any pointers about how to do this task?.
Thank you.
Related
I have a single DIV that can hold many different images based on user input. When the user is done configuring the application, the final output is the images that have been rendered (one-by-one) in the same DIV. To capture the image, I am using html2canvas. The problem is that once I start the loop to redraw the images as needed in the div and capture them, only the first image is actually captured each time.
To put it another way, it's as if the showShelf() function in the code below never executes.
var exportJSON;
var exportDeviceList;
var renderNumber;
function exportAll()
{
exportJSON = [];
exportDeviceList = [];
renderNumber = 0;
for (var i = 0; i < devices.length; i++)
{
var elements = devices[i].elements;
for (var j = 0; j < elements.length; j++)
{
exportDeviceList.push({site: devices[i].site, device: elements[j].id, name: elements[j].tid, config: elements[j].config});
}
}
renderNext();
}
function renderNext()
{
site = exportDeviceList[renderNumber].site;
device = exportDeviceList[renderNumber].device;
config = exportDeviceList[renderNumber].config;
showShelf(site,device,config);
html2canvas(document.getElementById("baseImage"), {allowTaint: true}).then(function (canvas)
{
exportJSON.push({tid: exportDeviceList[renderNumber].name, image: canvas.toDataURL("image/png")});
renderNumber++;
if (renderNumber < exportDeviceList.length)
{
renderNext();
}
});
}
I found my own answer: After performing the showShelf() function, I perform a setTimeout() function containing the actual html2canvas() call and the call to perform the next render.
First I write summarized pseudo code.
const ExcelSheet = new ExcelSheet() // excel.js library
const usersWithPlayedGames = await findAllUsers({ include: GameTable });
for (let i = 0; i < usersWithPlayedGames.length; i++) {
// Write some user data on Excel.
...
...
for (let j = 0; j < usersWithPlayedGames[i].length; j++) {
// Write some user's game on Excel
...
...
for (let k = 0; k < usersWithPlayedGames[i][j].length; k++) {
// Write some users's game's company data on Excel
...
...
}
}
}
res.send(ExcelSheet.toFile());
The actual code is pretty long.
And it take client req => res time almost 15sec.
I know my problem solution is not good.
I can do refactoring with this code.
But the real problem is it blocks another client request.
I search on google and find several solutions.
Node.js child process spawn.
Make with a callback function(I don't know exactly how to do).
Write more than a good algorithm.
What's the concept I'm missing from Node.js?
Please help me with a small favor.
Thank you.
You're porbably better off running this in a child process or somewhere else outside your web request thread, but if that's not an option, you could break the task up using something like setImmediate
const ExcelSheet = new ExcelSheet() // excel.js library
const usersWithPlayedGames = await findAllUsers({ include: GameTable });
const excelLoop = (index) => {
for (let j = 0; j < usersWithPlayedGames[index].length; j++) {
// Write some user's game on Excel
...
...
for (let k = 0; k < usersWithPlayedGames[index][j].length; k++) {
// Write some users's game's company data on Excel
...
...
}
}
if (index < usersWithPlayedGames.length) {
setImmediate(() => excelLoop(index + 1))
}
else {
res.send(ExcelSheet.toFile());
}
};
excelLoop(0);
Documentation for setImmediate
Community,
i am having some problems with my Angular 6 - App which i'm unfortunately not able to solve after hours of thinking & searching on google.
I've got a component that is displaying Meetings, Projects and Tasks in a Form. Those forms require a lot of data from different collections to select from (if the user wants to change something). All of those are being loaded in my ngOnInit:
ngOnInit() {
this.meetServ.getCompanyMeetings(false)
.subscribe(data => this.meetings = data as meeting[]);
this.deptServ.getCompanyDepartments()
.subscribe(data => this.depts = data as department[]);
this.CusServ.getCompanyCustomers()
.subscribe(data => this.customers = data as customer[]);
this.UserServ.getCompanyUsers()
.subscribe(data => {
this.users = data as user[];
})
}
When I'm done loading all the data, I want to set all of the dropdown menus to the right values. So I put a setDropdowns method in the subscription of the last http-request I am doing (also tried out of subscription).
The extend() Method is called by onclick event as soon as the User selects a Meeting:
extend(meetingID) {
document.getElementById("overlay").remove()
this.meetServ.getMeetingbyID(meetingID)
.subscribe(data => {
this.singleMeeting = data as meeting
this.init(); //gets all the projects by ID of selected Meeting
this.setMeetingAccessLevel();
this.setMeetingComments();
this.setDropdowns(); // tried like this
})
this.setDropdowns(); // and like this
}
and my setDropdowns() Method looks like this:
setDropdowns() {
var projectDivs = document.querySelectorAll("div.projectContent");
console.log(this.projects.length)
for (var i = 0; i < this.projects.length; i++) {
// Access Level
var opts = projectDivs[i].querySelector("#access").querySelectorAll("option");
(<HTMLOptionElement>opts[this.projects[i].accessLevel]).selected = true;
// Department
opts = projectDivs[i].querySelector("select#dept").querySelectorAll("option");
for (var j = 0; j < this.depts.length; j++) {
if (this.depts[j]._id == this.projects[i].department) {
opts[j + 1].selected = true
}
}
//Customer
opts = projectDivs[i].querySelector("select#proCustomer").querySelectorAll("option")
for (var k = 0; k < this.customers.length; k++) {
if (this.customers[k]._id == this.projects[i].customer) {
opts[k + 1].selected = true
}
}
//Official
var asd = (<HTMLSelectElement>projectDivs[i].querySelector("select#proinCharge")).querySelectorAll("option")
for (var l = 0; l < this.users.length; l++) {
/* if (this.users[l]._id == this.projects[i].inCharge) {
asd[l].selected = true
} */
}
}
}
But when I look at the console, this.projects.length is either 0 or 2 (which is the actual number of projects in that meeting). The thing is, when I get it to log 2, the projectDivs[i].querySelector("#access") part errors "Cannot read property 'querySelector' of undefined", which actually makes no sense, since projectDivs are generated like this:
<div class="projectContent" id="projectContent" *ngFor="let project of projects">
and console.log(this.projects.length) returns 2 earlier.
So projects are loaded but the HTML seems to not be loaded properly at that point.
Now for sure i googled this a lot and tried out stuff like jQuery document.ready and checked if document.readyState == complete, but it seems to only apply to the static document and not to the *ngFor generated elements.
So obviously my question in the end is: Is there any way to wait for all *ngFor generated elements or is there just a much easier way of doing this which is wasn't able to spot?
Thanks in advance for all the upcoming answers.
Greetings
I was coding using the google scripts, when I came across a problem I've been struggling with for a couple days now. I am using Code.gs (a default page in creating a web app in google), when I called in data from a google spreadsheet to try and display it on a webpage. I had no problems with calling in the data add storing it into a array but now I am struggling with trying to return it to my javascript code. Can this be done or is there something else I can do to fix it? My code is below.
function getContents()
{
var sheet = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/1xum5t4a83CjoU4EfGd50f4ef885F00d0erAvUYX0JAU/edit#gid=0&vpid=A1');
var range = sheet.getDataRange();
var values = range.getValues();
for (var i = 0; i < values.length; i++) {
var education = [];
for (var j = 0; j < values[i].length; j++) {
if (values[i][j]) {
if(j==1){
education[education.length] = values[i][j];
}
}
}
}
Logger.log(education);
return education;
}
From that Code.gs code i want it to return it to a Javascript function that says this:
function onNew(){
var input = google.script.run.getContents();
for(var = 0; i<input.length; i++)
{
$("#main").append("<div id='class'>"+input[i]+"</div>);
}
}
and whenever I try to run it says that it causes an error because it is undefined. Thanks in advance! Anything helps!
You need to use the withSuccessHandler(). Your variable input will not receive the return from google.script.run.getContents()
Separate out the client side code into two functions:
HTML Script
function onNew() {
google.script.run
.withSuccessHandler(appendEducationHTML)
.getContents();
};
function appendEducationHTML(returnedInfo) {
console.log('returnedInfo type is: ' + typeof returnedInfo);
console.log('returnedInfo: ' + returnedInfo);
//If return is a string. Convert it back into an array
//returnedInfo = returnedInfo.split(",");
for (var = 0;i < returnedInfo.length; i++) {
$("#main").append("<div id='class'>"+returnedInfo[i]+"</div>);
};
};
I am trying to render an html page that contains all of the posts that a user has received. Right now the issue I am having (shown under Way 1) is that when I call the function renderPosts after the web socket is received, only the first post in the array is rendered (the array has more than one post in it).
On the other hand, Way 2 in which I have no for loop and instead manually render each post works in that all four posts are rendered. But I need to be able to work with an arbitrary number of posts which is why I need to use the for loop.
I am using socket.io and javascript.
Way 1:
socket.on('postsToRender', function(arrayOfPostsToRender) {
renderPosts(arrayOfPostsToRender);
});
function renderPosts(arrayOfPostsToRender) {
for (var index = 0; index < arrayOfPostsToRender.length; index++) {
renderPost(arrayOfPostsToRender[index]);
}
}
function renderPost(postToRender) {
var feed = document.getElementById("feed");
var postContent = document.createTextNode(postToRender.content);
var post = document.createElement("div");
post.appendChild(postContent);
feed.appendChild(post);
}
Way 2:
socket.on('postsToRender', function(arrayOfPostsToRender) {
renderPost(arrayOfPostsToRender[0]);
renderPost(arrayOfPostsToRender[1]);
renderPost(arrayOfPostsToRender[2]);
renderPost(arrayOfPostsToRender[3]);
});
function renderPost(postToRender) {
var feed = document.getElementById("feed");
var postContent = document.createTextNode(postToRender.content);
var post = document.createElement("div");
post.appendChild(postContent);
feed.appendChild(post);
}
Try this:
function renderPosts(arrayOfPostsToRender) {
for (var index = 0; index < arrayOfPostsToRender.length; index++) {
(function(i){
renderPost(arrayOfPostsToRender[i]);
})(index);
}
}