Hello I am new in WebVR and I will be pleased If you can help me.
I want to update my AFRAME init() variable after onchange my input in test.js and callback aframe(rebuild Aframe component). I would like do somethink like useEffectfrom React.
I have two file test.js and aframe.js
test.js
const el = document.getElementById("inputItem")
el.setAttribute("type", "date")
el.addEventListener('input', (e)=> { console.log(e.target.value) }
//other logic
aframe.js
AFRAME.registerComponent("test", {
init(){
this.input = document.getElementById("inputItem")
this.input.addEventListener('input', (e)=> { console.log("input changed", e.target.value) } );
console.log("my input value", this.input)
}
update(){
if( this.input.value != document.getElementById("inputItem").value )
{this.input = "New input"
console.log("input changed", this.input)
}
}
// some code here to build aframe element and append it to html
}
so my console.log function inside aframe work only one time. After onchange input my update function doesn't response. I know the problem is aframe component is calling only one time.
I tried this answer and read about component. I don't know how to recall/rebuild afraime component after changing my input.
Looks like you've mixed two ways of doing this:
1. Using setAttribute()
to trigger the update()
functions.
The update
function in the custom component is called:
init
setAttribute(<component_name>)
Here's an example of triggering update
with setAttribute
from an "external" js
file (same behaviour, as long as the script is loaded after the <input>
element is attached) :
const input = document.getElementById("logtext"); // grab the input
input.addEventListener("input", e => {
// on each 'input' event
const text = e.target.value; // extract the text
// set the [logger] "text" attribute, to trigger the update
document.querySelector("[logger]").setAttribute("logger", "text", text);
})
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
<script>
AFRAME.registerComponent("logger", {
schema: {
text: {
default: ""
}
},
// on any update
update: function() {
this.el.setAttribute("text", "value", this.data.text); // update the text component
}
})
</script>
<div style="position: fixed; z-index: 999">
<label for="logtext">Text to be rendered:</label>
<input type="text" id="logtext" name="logtext"><br><br>
</div>
<a-scene>
<a-text position="-1 1.75 -3" value="" color="black" logger></a-text>
<a-box position="0 1 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
</a-scene>
2. Using event listeners.
You can add any logic you want to the event listener callbacks. It can modify you own component, it can modify other components.
Here's an example of modyfing another component with setAttribute()
in reaction to an event coming from the <input>
element:
<script src="https://aframe.io/releases/1.4.0/aframe.min.js"></script>
<script>
AFRAME.registerComponent("logger", {
init: function() {
// grab the input element
const input = document.getElementById("logtext");
// on "input", do whatever you need with the updates
input.addEventListener("input", e => {
const text = e.target.value; // extract the text from the event
this.el.setAttribute("text", "value", text); // update the text component
});
}
})
</script>
<div style="position: fixed; z-index: 999">
<label for="logtext">Text to be rendered:</label>
<input type="text" id="logtext" name="logtext"><br><br>
</div>
<a-scene>
<a-text position="-1 1.75 -3" value="" color="black" logger></a-text>
<a-box position="0 1 -3" rotation="0 45 0" color="#4CC3D9"></a-box>
</a-scene>
I think the first option is similar to react since:
schema
is similar to keeping a component "state" (as in useState
)update
function reacts to the component changes (as is useEffect
)