How to get reference auto generated elements in React? - javascript

I am currently working with react but I am now stuck with an error that I don't know how to fix. I am using mCustomScroll bar and this library automatically generates an element with the id of MCSB_1. This means that I can't attach a "ref" to it. The only element that I can attach is a ref to is the parent element to the auto generated element.
For example my structure is as follows;
componentDidMount() {
$(this.refs.messagesPanel).mCustomScrollbar(); //The mCustomScrollbar is a plugin
}
render() {
return (
<div id="messagesPanel" ref="messagesPanel"></div>
);
}
The problem is: that when I call mCustomScrollbar(); the plugin auto generates a div in messagesPanel which I do not know how to access:
<div id="messagesPanel">
<div id="MCSB_1"></div>
</div>
Basically, i'm asking how do I access the "MCSB_1" if I can't attach a ref to it.
Thanks!

One option could be using jQuery's find function from your messagePanel object
componentDidMount() {
...
}
someFunction() {
let yourElement = $(this.refs.messagesPanel).find('#MCSB_1');
}

Related

How do I add style to a react element within the return function?

I'm trying to add style to an element in my return of a react component, but I want to achieve this without adding a class. My text editor auto fills a style option, but I believe the syntax is wrong, since when trying to add a function on an onClick event, its a little different when its in the return of a react element. For example, instead of
onClick=function()
its
onClick={() => {function()}}
I'm hoping that instead of style={"background-color: green;"} its a different syntax to actually allow style changes once it hits the dom.
In-line styles can be done, and here is a code example as you have not provided one.
for example, lets inline style an h1 tag
<h1 style={{background-color:'green', color:'white'}}>This is a tilte</h1>
more can be found here
additionally, I would not recommend inline styling as it's not industry-standard and can cause your code to become bloted.
Style tags in react can indeed contain a references to functions.
I am not fully sure if you are working with React component classes or component functions, but your syntax can besides as follows. Create a variable called customStyle which will contain a function that returns your required style object:
customStyle = () => { return { color: 'red' } };
You can then reference customStyle inside markup as follows:
<div style={this.customStyle()}>My Element</div>
idont know if i understood your question well, You can achieve what you want by making a style state, then mutate it whatever style you want with setState
const [style, setStyle] = useState({})
const App = () => {
return <div style={style}>
<button onClick={() => setStyle({color: 'red'})}>handler button </button>
</div>
}

How to specify a child component to drag its parent component in React?

I'm currently working on a terminal emulator project using React and styled-components. I want to add dragging feature to the terminal. Everything is good, except one thing: I want to click and hold the title bar to drag the terminal, not somewhere else.
Here is my base component: https://codesandbox.io/s/still-http-jxxex
I don't want to use any plugins or libraries because I want to know how it works. So are there any ways to achieve this just by React and javascript? Every comments are appreciated to me.
Well, after reading MDN docs
here is a very simplified version of d&d(the rest is up to you so please read the docs):
link to codesanbox
Bellow is the MDN example my answer based on:
<script>
function dragstart_handler(ev) {
// Add the target element's id to the data transfer object
ev.dataTransfer.setData("application/my-app", ev.target.id);
ev.dataTransfer.dropEffect = "move";
}
function dragover_handler(ev) {
ev.preventDefault();
ev.dataTransfer.dropEffect = "move"
}
function drop_handler(ev) {
ev.preventDefault();
// Get the id of the target and add the moved element to the target's DOM
const data = ev.dataTransfer.getData("application/my-app");
ev.target.appendChild(document.getElementById(data));
}
</script>
<p id="p1" draggable="true" ondragstart="dragstart_handler(event)">This element is draggable.</p>
<div id="target" ondrop="drop_handler(event)" ondragover="dragover_handler(event)">Drop Zone</div>
After days of searching, I found out the problem is that I triggered onMouseDown in window (globally).
In order to do this, I use a function that passed to the child component to update its parent component's states, which is onMouseDown, then got rid of the function in useEffect.
Here's my final solution: https://codesandbox.io/s/admiring-liskov-puu6g

Implement Jsignature within vuejs component

I'm new to Vue and trying to implement Jsignature within a 'custom' Vuejs component.
My solution is based on: https://v2.vuejs.org/v2/examples/select2.html
It should be straight forward however I don't get it working, the solution I got so far results in the following error:
'Jsignature' is defined but never used
import Jsignature from '../../lib/jsignature
The component containing the signature.
<template>
<div>
<app-signature></app-signature>
</div>
</template>
<script>
import Signature from './signature/Signature.vue'
export default {
components: {
appSignature: Signature
}
}
</script>
The signature component.
<template>
<div id="signaturecanvas"></div>
</template>
<script>
import Jsignature from '../../lib/jsignature'
export default {
data () {
return {
signature: ''
}
},
methods: {
initial () {
var element = ('#signaturecanvas')
element.Jsignature.jSignature()
}
},
created () {
this.initial()
}
}
</script>
<style></style>
Never worked with Jsignature but I suppose you use it as a jquery plugin.
The issue you have is right at the this.$signaturecanvas. This is somehow a wrong way to get the div via jQuery.
var element = ("#signaturecanvas") or var element = $(this.$el) if you want to selected the whole component. $el refers to the identifier of the current vue component instance and basically is the first tag from the component. Choose the appropriate way depending on what you want to select and you should get it working.
Instead of importing JQuery and JSignature, I made the choice to use signature pad. https://github.com/szimek/signature_pad
This 'plug-in' is in native javascript/html5 which makes my application less constraint to external libraries like JQuery.

EmberJs - Is there a way to tell ember to insert the main-view after the rootElement?

Hi I would like to know if the is a way to tell ember to initialize immediately after the root Element?
For example I have this DOM Structure:
<div id="#bodyContent" class="ember-application">
<div data-name="ContentPlaceHolderMain">
</div>
<div id="ember357" class="ember-view">
</div>
</div>
But I Want ember to be first on the DOM:
<div id="#bodyContent" class="ember-application">
<div id="ember357" class="ember-view">
</div>
<div data-name="ContentPlaceHolderMain">
</div>
</div>
In my enviroment.js file I have this line:
ENV.APP.rootElement = "#bodyContent";
Is there any way to achieve this?
Ember uses appendTo to insert it's view inside root element. But you could override didCreateRootView of ember instance and change it to use prependTo. Have a look how Fastboot does this.
Update: This is an instance-initializer to overwrite didCreateRootView.
export function initialize(appInstance) {
appInstance.didCreateRootView = function(view) {
// overwrite didCreateRootView
};
}
export default {
name: 'prepend-to',
initialize
};
ember/glimmer does not provide an prependTo method. You have to implement that one on your own following the implementation of appendTo.
Please also note that didCreateRootView is a private hook. Don't expect that one to keep stable over time.
In general I would not recommend to go this path if there is any other way to achieve your goal. Please consider adding a container for ember at desired position. If you don't have control over HTML markup you might could add a container using jQuery before initializing ember.
Update 2:
import jQuery from 'jquery';
export function initialize(appInstance) {
appInstance.didCreateRootView = function(view) {
let containerId = 'ember-container';
jQuery('<div>').prop('id', containerId).prependTo(jQuery(this.rootElement));
view.appendTo(`#${containerId}`);
};
}
export default {
name: 'prepend-to',
initialize
};
This is not exactly what you've asked for but it's much easier to achieve. If your HTML markup looks like <body><div id="existing-content"></body> and body as default root element above instance initializer will add another div #ember-container before #existing-content and using this one as embers root element.
Update 3:
You find an ember-twiddle here: https://ember-twiddle.com/43cfd1ae978b810f2e7cf445f9a3d40c?openFiles=instance-initializers.root-element.js%2C
If you inspect DOM you will see that ember root element is wrapped by <div id="ember-container"></div>. This wrapper is append to rootElement. So it's before any existing content in rootElement. I guess it's not possible to define a custom index.html in ember-twiddle so I can't demonstrate this one. But you could easily test yourself.

Angular 2 - Dynamically create/inject component into specific element inside *ngFor loop

I am looping through a list of metrics and inside each loop there is a button that would be clicked to render a graph at a specific div within the HTML of the loop. The graph is a separate component, however I cannot seem to figure out how to target the correct HTML element to load the graph component into. I started by creating a component rendering function and call it like this:
loadMetricGraph(metric) {
let selector = "[id=metricGraph-" + metric.id + "]";
this.renderComponent(LineGraphHorizontalComponent, selector, metric.data);
}
renderComponent(componentClass, selector, data) {
return this.compiler
.compileComponentAsync(componentClass)
.then((factory:ComponentFactory<any>) => {
let cmpRef:ComponentRef<any> =
factory.create(this.injector, null, selector);
cmpRef.instance.inputData = data;
(<any>this.appRef)._loadComponent(cmpRef);
return cmpRef;
});
}
In the loop I have a div that would be the target for the loaded component, however I am stuck on how to pass the correct selector to the renderComponent() function. I have attempted to use
id="graphData-{{ metric.id }}" And then a selector of "[id=graphData-" + metric.id + "]". I know this is not the correct way to do this, but I am not sure how to proceed.
You can't dynamically add HTML and get components or directives created for this HTML. If you want to dynamically add components then you need to use ViewContainerRef.createComonent.
See Angular 2 dynamic tabs with user-click chosen components shows how to do this declaratively using a helper component.

Categories

Resources