I'm relatively new to React (and Javascript, for that matter) so please bear with me.
To put my question shortly: how do i trigger a resize event on my window/component in React?
Now below is a little more context, which may actually prove that i'm asking a wrong question here.
I'm trying to create a small app with several tabs. The component is taken from BlueprintJS framework. The content of these tabs is loaded using a javascript API, which in turn uses RESTful requests to a remote application. The content that will be rendered in my tabs is some tables and charts.
Here is a caveat. The actual rendering of those tables and charts is performed by the javascript API i have to use, not by my React app. I have to pass an ID of a to the API, and it will render returned content into that .
The problem: Only the content of the default active tab is rendered correctly. If i switch to any other tab of my React application, the content is not rendered. HOWEVER if i resize the window the content is rendered instantly (i believe this is handled by the javascript API i'm using). Also if i update parameters of the currently active tab to make the API load updated content from the remote application, the content is also rendered in the active tab.
So i figured if i can simulate the resize event when switching between tabs i can get my content to render.
I tried setting a conditional class on my as depending on whether the current tab is active or not:
<div className={this.state.SelectedTabId === "tab1" ? "container" : "hidden"}>
where "container" and "hidden" have different width configured in CSS file, but this doesn't help. I also tried to directly manipulate the DOM (at least as a test) but even that didn't make a difference:
let e1 = document.getElementsByClassName('container')[0];
e1.width = e1.scrollWidth - 1;
renderedElement.resize(); //this is an API method which is supposed to re-render the content it returns
Related
I have created one spa using JQuery. SPA is done via writing a custom router where we add visible classname to a page div to make that page visible and we remove the same classname from all the other pages using jquery like this,
$(".main-content .page").removeClass("visible");
const page = $(`#${pageId}`);
page.addClass("visible");
Now I am migrating this site to use react components here and there through out the website. I have one component on one of the page that shows product data based on the id in the URL but the problem is that it doesn't rerender even if I change the URL. It is not able to detect the change as state or props are not changing.
is there a way to force rerender this component from my other JS code?
The solution was pretty straight forward but it is not mentioned anywhere.
The official guide says to use this below code at the end of the file so that when our js file will be loaded by the browser and run then it will render our react code but the thing is we can call this method from anywhere to force rerender our component/ replace our component with the new instance.
To force rerender it, calling below method that adds the react code to the div worked.
ReactDOM.render(<ProductDetails />, document.getElementById("product-details"));
Using this we can even pass the new props also if we want to.
Suppose you have some kind of listing and you allow this listing to be rendered via CSS either as a list or as a grid (via a varying CSS class or data attribute). Since this is purely a rendering issue it required not (re)processing by the web server, thus you can also simply implement the switch on the client side via JavaScript.
However, suppose you want to save the client's view mode choice, e.g. in the localStorage. Now when the page is rendered, the appropriate view mode needs to be restored.
But what is the best practice here in order to prevent the switch from the default view to the saved view to be visible when the content is above the fold?
Consider the following crude example: http://jsfiddle.net/yaubvq8d/27/
Here the JavaScript for changing the view mode and also loading the saved view mode from the localStorage is at the end of the body, which is obviously not ideal. To visualize the problem I also integrated an externally loaded JavaScript, that blocks rendering of the page for 2 seconds - so it takes at least 2 seconds, before the JavaScript for managing the view mode is actually executed. During these two seconds you first see the default view (which is the grid view) and then it would switch to whatever view you had previously selected (to test this you obviously have to click on "List" first and then run the fiddle again).
The only obvious solution I can think of is defining the view mode in a parent container (let's say the body) and then execute the JavaScript to load the view mode from the local storage right after the starting tag of the parent container.
But are there any other best practices, that I might miss?
We have a parent site that provides the real estate for our applications to be added. The flow is described as below
Parent site has a menu.
One of the "links" on the menu points to our
application
When you click on it, the parent site internally parses
the response from our application (including html and javascript)
and loads it within a container. Sort of a portlet. This parsing is problematic, because once the javascript is loaded, it remains in the head tag.
Thereafter, we can use our code to control the application in a SPI manner.
Problem arises, when the user clicks on the menu again, because steps 1-4 get repeated. Thus we end up reloading javascript, which fails spectacularly. Some of the problems include
Angular is reloaded.
Modules get reloaded.
If I defer the loading of Angular conditionally via document.write, then I have to ensure that angular is loaded before the modules are defined.
If I manually bootstrap the application, then I cannot bootstrap it again and I need flags to maintain.
I was able to write a script to ensure that everything is loaded only once, but now the problem is that the DOM does not get "processed" once the user clicks the link again. It is as if the entire DOM content has refreshed with the angular tags and directives, and the javascript is already loaded, but it does not "process" this new DOM content.
What can I do to ensure that newly added DOM via a third party plugin/script/code is recognized by existing angular code?
I'm making a game using JavaScript, currently I'm using window.location = "somepage.html" to perform navigation but I'm not sure if that is the correct way to do it. As I said in the title I've choosed Blank App Template so I do not have any navigator.js or something like.
Can you guys tell me the best way to do it?
Although you can use window.location to perform navigation, I'm sure you've already noticed a few of the downsides:
The transition between pages goes through a black screen, which is an artifact of how the underlying HTML rendering engine works.
You lose your script context between pages, e.g. you don't have any shared variables or namespaces, unless you use HTML5 session storage (or WinRT app data).
It's hard to wire up back buttons, e.g. you have to make sure each destination page knows what page navigated to it, and then maintain a back stack in session storage.
It's for these reasons that WinJS + navigator.js created a way to do "pages" via DOM replacement, which is the same strategy used by "single page web apps." That is, you have a div in default.html within which you load an unload DOM fragments to give the appearance of page navigation, while you don't actually ever leave the original script context of default.html. As a result, all of your in-memory variables persist across all page navigations.
The mechanics work like this: WinJS.Navigation provides an API to manage navigation and a backstack. By itself, however, all it really does is manage a backstack array and fire navigation-related events. To do the DOM replacement, something has to be listening to those events.
Those listeners are what navigator.js implements, so that's a piece of code that you can pull into any project for this purpose. Navigator.js also implements a custom control called the PageControlNavigator (usually Application.PageControlNavigator) is what implements the listeners.
That leave the mechanics of how you define your "pages." This is what the WinJS.UI.Pages API is for, and navigator.js assumes that you've defined your pages in this way. (Technically speaking, you can define your own page mechanisms for this, perhaps using the low-level WinJS.UI.Fragments API or even implementing your own from scratch. But WinJS.UI.Pages came about because everyone who approached this problem basically came up with the same solution, so the WinJS team provided one implementation that everyone can use.)
Put together then:
You define each page as an instance of WinJS.UI.Pages.PageControl, where each page is identified by its HTML file (which can load its own JS and CSS files). The JS file contains implementations of a page's methods like ready, in which you can do initialization work. You can then build out any other object structure you want.
In default.html, define a single div for the "host container" for the page rendering. This is an instance of the PageControlNavigator class that's defined in navigator.js. In its data-win-options you specify "{home: }" for the initial page that's loaded.
Whenever you want to switch to another page, call WinJS.Navigation.navigate with the identifier for the target page (namely the path to its .html file). In response, it will fire some navigating events.
In response, the PageControlNavigator's handlers for those events will load the target page's HTML into the DOM, within its div in default.html. It will then unload the previous page's DOM. When all of this gets rendered, you see a page transition--and a smooth one because we can animate the content in and out rather than go through a black screen.
In this process, the previous page control's unload method is called, and the init/load/processed/ready methods of the new page control are called.
It's not too hard to convert a blank app template into a nav template project--move your default.html/.css/.js content into a page control structure, add navigator.js to default.html (and your project), and put a PageControlNavigator into default.html. I suggest that you create a project from the nav app template for reference. Given the explanation above, you should be able to understand the structure.
For more details, refer to Chapter 3 of my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript, Second Edition, where I talk about app anatomy and page navigation with plenty of code examples.
In some cases I need to reinitialize my Sencha Touch app. Till now I just used location.reload() to do this. However this is really bad for the user experience as the whole HTML page, JS and CSS will be reloaded, too.
So I'm looking for an easy and clean way to reset and reinitialize my app without reloading the whole page.
I tried to do something like Ext.Viewport.removeAll(true, true) to remove all view components from the viewport. But this results in some errors, when you masked the viewport before or if you showed some dialogs before. Sencha keeps some references to objects created while masking the view or showing a dialog, that won't be present any more after removing all components from the viewport:
Ext.Msg.alert()
Ext.Viewport.removeAll(true, true)
Ext.Msg.alert() // => will raise `TypeError: Cannot read property 'dom' of null`
How do you reinitialize your app without reloading the whole page? Is there any way to do it "the nice" way?
You can relaunch the app by calling the launch function of you application.
Suppose you application name is my_app, you can relaunch the app using:-
my_app.app.launch()