Backbone Marionette, Render Region if not already rendered - backbone.js

So I want to render a sidemenu itemview only if it's not rendered already. This is so unessecary I don't force unessecary re-rendering.
I have figured a solution to render a view if not rendered in a region already.
Take the following example in a controller object called by a router.:
Admin.showIndex= function(){
if (!MyApp.layout.sidepanel.currentView || !(MyApp.layout.sidepanel.currentView instanceof AdminSidePanel)){
MyApp.layout.sidepanel.show(new AdminSidePanel());
}else{
alert("Already rendered sidepanel!");
}
// More stuff!
}
Is this a good way to do it? It works like this:
If I F5 refresh the page /#admin , the sidepanel is rendered.
If I go in forexample /#admin/submenu and back to #admin, sidepanel is not rendered again.

Looks good to me. I've used similar logic in my project.
I prefer this approach over explicitly maintaining a global state variable in MyApp.

Related

React App - materialize-css doesn't initialize on first render

I am building a 'Add Item' functionality with React and materialize-css. For some reason, the materialize-css components are not being initialized when i first navigate into the page they are on. They do initilize though after I refresh the page. I spent several hours trying to figure out the problem but couldn't find what i did wrong. I installed materialize-css via npm and here is my code where i initiliaze the materialize-css components:
componentDidMount() {
var context = this;
document.addEventListener('DOMContentLoaded', function() {
var elemsTwo = document.querySelectorAll('select');
var instancesTwo = M.FormSelect.init(elemsTwo, {});
var elemsThree = document.querySelectorAll('.timepicker');
var instancesThree = M.Timepicker.init(elemsThree, {});
});
}
Like I said it does work fine after refreshing the page, but when just navigating into the page, it doesn't work. Below are the screenshots on how the page looks before and after refreshing (refer to fields 'Gender' and 'Spoken Languages' on screenshots). Thanks in advance.
Its a bad practice to use React while using DOMContentLoaded on your own. Your main problem is, that DOMContentLoaded is fired when your content is ready, but this does not mean that React has done its initialisation. Also, DOMContentLoaded is not fired when you navigate between pages using React.
You may use a library that already closes this gap, like https://material-ui.com/.
If you want to stay with your concept, you have to call the code you run in your componentDidMount also when your navigator changed the page.

React route url and view changes but component function still active. Why?

I have an event function that is triggered by a button click. It's purpose is to keep the body position fixed keeping it from scrolling until you click the button again to close/toggle it off.
It works fine but, when I click to another page without toggling it off it is still active. Meaning the new page will not scroll because the body position is fixed.
I am new to React FYI
My code:
bodyFixed(event) {
document.body.classList.add('body-fixed');
}
bodyRelative(e) {
document.body.classList.remove('body-fixed');
}
I am using react-static withRouteData, RouteData, Router and I have no issues on those pages. But, on pages like an article page where the route doesn't change the same way. This is where I am seeing the problem.
Is there something I can wrap it with so that when I click to a new page it goes back to default?
Please first ask if you need more information and I will gladly add more.
Yes, you can call bodyRelative method in componentWillUnmount lifecycle hook to unset the class. Something along those lines:
componentWillUnmount() {
this.bodyRelative()
}

React Component: Foundation Modal (Reveal) won't open

So I've just started learning React and Redux, so I apologize if this is a very noobish question. But I've emptied my Google quote, and can't find anything that helps me.
My problem is: I work on a site with React, Redux, and Foundation 6. One of my React components have a link, that when clicked, should open a Modal with a specific warning for that link. So I've created a component with my modal markup:
ComponentModal.js:
import React, { PropTypes } from 'react';
const Modal = () => (
<div className="reveal" id="exampleModal1" data-reveal>
<h1>Awesome. I Have It.</h1>
</div>
);
export default Modal;
The component with a link renders some stuff, but basically have a
<a data-open="exampleModal1">Click me for a modal</a>
tag in it's render.
And although inspecting the page confirms that the markup for the modal exists, nothing happens when i click the link.
If I move the popup from the component, and into the DOM, the link works.
Some trial and error shows me, that if i manually run $(document).foundation(); in the console when ComponentModal is rendered, the popup works as intended.
So my question is kinda two questions:
1. How do I, in Redux, run $(document).foundation(); when my ComponentModal is done rendering? Maybe I'm wrong, but I don't have the componentDidMount() method available to me, where it might make sense to make that call?
2. Is this a totally wrong way to go about it?
Hope it's not too confusing and not too dumb a question :)
FYI, this question/solution has nothing to do with REDUX!
The problem is that you're trying to use React AND Jquery to make your page do cool things.
You should really choose one or the other.
$(document).foundation() is a Jquery library.
Instead you should use something like React Foundation which removes the jquery dependency and gives you foundation components built with react.
You can do $(document).foundation() in React inside componentDidMount of the component that has the reval modal or better yet You can do this inside componentDidMount of the top most partent in your app.
componentDidMount in React runs once after all the DOM nodes related to that component is mounted. What $(document).foundation() does, if it runs inside componentDidMount, is that it binds event handlers on the elements that have foundation realated attributes like data-dropdown or data-reveal.
componentDidMount() {
$(document).foundation();
}

Angular 2 setting a new value does not trigger an input change event

I'm running into a weird case that only seems to happen upon first loading a component on a heavily based component page (loading 30+ components).
#Component{
selector: <parent-component>
template: `<child-component [myObject]=myObject>
}
export class ParentComponent {
private myObject:DTOValue;
constructor(service:MyService){
service.getDTOValue().subscribe((dtoValue:DTOValue) => {
this.myObject = dtoValue;
});
}
}
#Component{
selector: <child-component>
template: `<div></div>
}
export class ChildComponent {
#Input set myObject(value:DTOValue) => {//do something};
constructor(){
}
}
In this code, the Parent is going to get a value to a child as an input. This value comes from a request at a later time, so when the child is first initialized, the input could be undefined. When the value does get returned from the request and is set on the variable myObject, I'd expect that the child component would receive an input event being triggered. However, due to the timing, it seems like this is not always the case, especially when I first load a page that contains a lot of files being loaded.
In the case that the child component doesn't receive the input, if I click else where on my page, it seems to now trigger the change detection and will get the input value.
The 2 possible solutions I can think of that would require some large code changes so I want to make sure I choose the right now before implement them.
Change the input to be an Subject, so that I push the input value which should ensure that a correct event is triggered(this seems like overkill).
Use the dynamic loader to load the component when the request as return with the correct value (also seems like overkill).
UPDATE:
Adding a plnker: http://plnkr.co/edit/1bUelmPFjwPDjUBDC4vb, you can see in here that the title seems to never get its data bindings applied.
Any suggestions would be appreciated.
Thanks!
If you can identify where the problem is and appropriate lifecycle hook where you could solve it, you can let Angular know using ChangeDetectorRef.
constructor(private _ref: ChangeDetectorRef)
method_where_changes_are_overlooked() {
do_something();
// tell angular to force change detection
this._ref.markForCheck();
}
I had a similar issue, only with router - it needed to do redirect when/if API server goes offline. I solved it by marking routerOnActivate() for check...
When you trigger change detection this way a "branch" of a component tree is marked for change detection, from this component to the app root. You can watch this talk by Victor Savkin about this subject...
Apologize, the issue ended up being my interaction with jQuery. When I triggered an event for a component to be loaded, inside of the jQuery code, it wouldn't trigger the life cycle. The fix was after the code was loaded to then call for a change detection.

How to trigger CKEditor's widget upcast function after DOM rerendering?

I initialize CKEditor in a React component like this:
render: () ->
<div ref="editable" dangerouslySetInnerHTML={{__html: #props.html}} />
componentDidMount: () ->
#editor = AlloyEditor.editable(#refs.editable, {extraPlugins: AlloyEditor.Core.ATTRS.extraPlugins.value + 'plugins go here'})
#editor.get('nativeEditor').on('blur', (event) =>
#props.handleChange())
//At this point the #props.html changes and the component is re-rendered
I define widgets following this tutorial. The appropriate html elements are properly recognized as widgets and everything works fine until the 'blur' event is fired. After the component is re-rendered, the widgets' upcast functions don't get invoked again and the html elements don't become widgets any longer.
I thought that I could use methods such as checkWidgets and initOnAll in the componentDidUpdate method, but they only work for widget candidates with .cke_widget_new class. As far as I understand, the upcasting happens at the data (html) processing stage, and it looks like the editor doesn't process html again after DOM was re-rendered. What can I do about this? Thanks!
Update: Eventually oleq's solution worked for me. I added:
componentDidUpdate: () ->
data = #editor.get('nativeEditor').getData()
#editor.get('nativeEditor').setData(data)
The only problem is that this (and probably any other) solution doesn't work with the blur event, which was a bad event choice, because it is also triggered right before the user adds a widget by pressing a button. I replaced this event with another one that seems to work for me at least for now.
You can use editor.widgets.checkWidgets() as documented here:
https://docs.ckeditor.com/ckeditor4/latest/api/CKEDITOR_plugins_widget_repository.html
The general idea is that it checks all the widgets in the document and refreshes ones that have not been made widgets yet.
OR if you only want to init one widget that you have a reference to, do it with initOn() documented on the same page.

Resources