React.js - REF undefined - javascript

When I test the following code I receive a console error that newText is undefined, am I declaring the val var correctly or am I missing something?
val = ReactDOM.findDOMNode(this.refs[newText]);
renderForm: function() {
return (
<div className="note">
<textarea ref="newText" defaultValue={this.props.children} className="form-control"></textarea>
<button onClick={this.save} className="btn btn-success btn-sm glyphicon glyphicon-floppy-disk"></button>
</div>
)
},

newText here needs to be either a string ("newText") or should use dot notation instead. Using just newText means you're trying to read the value of a variable with that name (which will return undefined).
Change:
this.refs[newText]
To:
this.refs["newText"]
Or:
this.refs.newText

I know it's very late to answer this but I came across the same problem.
I added and update the following sources:
src= "https://unpkg.com/react#15/dist/react.js">
src="https://unpkg.com/react-dom#15/dist/react-dom.js">
It worked for me.
Hope you already found a solution for this.
Cheers!

use this.refs.newText rather than this.refs[newText].

Related

Storing an integer variable in local storage in alpine.js

I wanted to store an integer value in local storage using alpine.js
There is a button that increments the value by 1 when pressed.
Here is how I thought it should be:
<div id="greeting" class="inner" x-data="{ $store.integer: 0 }">
<button class="button bouncy" #click="$store.integer+=1" x-text="$store.integer + ' is the number'"></button>
</div>
<script>
document.addEventListener('alpine:init', () =>
Alpine.store('store', integer)
})
</script>
This didn't work. I tried some other implementations, but none of them seemed to work. I also tried not adding the $store, since it showed the integer as "undefined" when I did that.
Alpine has the persist plugin which looks like it might suit your needs.
https://alpinejs.dev/plugins/persist
<div x-data="{ count: $persist(0) }">
<button x-on:click="count++">Increment</button>
<span x-text="count"></span>
</div>
You have a couple of mistakes in the example code. The corrected version is the following:
<div id="greeting" class="inner" x-data="{}">
<button class="button bouncy" #click="$store.integer += 1" x-text="$store.integer + ' is the number'"></button>
</div>
<script>
document.addEventListener('alpine:init', () => {
Alpine.store('integer', 0)
})
</script>
When you create a new variable in the store, the first argument is the name of the variable, the second is its initial value.
In the component, you don't have to recreate the variable in the x-data attribute, since it is defined in the alpine:init hook. So you can use just an empty x-data (assuming you don't have other variables in the component).
You have a missing { after =>.

alert value of button by onClick

I have a page with a lots of buttons from PHP output with each buttons having different values:
<button class='add' value=".$row['cat_no']." onClick='addItem(value)'>Add To Cart</button>
$row['cat_no'] is data from mysql.
I want to check the button's value when I click it, so I use native JS below:
<script>
function addItem(value) {
alert("this.value");}
</script>
It is not working...it just return this.value. In this case I don't think it is suitable to assign Id to getElementbyId, Pls help to check my mistake or suggest solution. Thanks.
Pls: I dont want to use JQUERY, just native JS.
Use alert(elmt.value); like below. you should pass this to the function
<button class='add' value="test value" onClick='addItem(this)'>Add To Cart</button>
<script>
function addItem(elmt) {
alert(elmt.value);
}
</script>
the code below helps you retrieve the value of the element that triggered the event:
<button class='add' value="test value" onClick='addItem(this)'>Add To Cart</button>
<script>
function addItem(sender) {
alert(sender.value);
}
</script>
However, this is filled with code smells.
I would suggest doing the code below
<button id='add-to-cart' class='add' value="test value">Add To Cart</button>
On a separate JS file:
(function() {
function _onLoad() {
var addToCartButton = document.getElementById("add-to-cart");
addToCartButton.addEventListener("click", _onAddToCartClicked);
}
function _onAddToCartClicked() {
var sender = this;
alert(sender.value);
}
document.addEventListener("DOMContentLoaded", _onLoad, false);
})();
This approach ensures that:
Concerns are separated between HTML and JS
External JavaScript file would be cached which results to faster page load time.
UI would render faster since there are no inline scripts
Global namespace won't be polluted
You don't really need this in your function, just use value. And also remove double quotes, because you need to alert function's parameter, not string, like this:
function addItem(value) {
alert(value);
}
Here is the working example:
function addItem(value) {
alert(value);
}
<button class='add' value="yourValue" onClick='addItem(value)'>Add To Cart</button>
Or you can pass the element to function using this, and then get the needed attribute value from addItem method:
function addItem(item) {
alert(item.value);
}
<button class='add' value="yourValue" onClick='addItem(this)'>Add To Cart</button>

ng-if doesn't works as expected

I have a buttons array in my model, and an 'ng-if' in the template for each button:
self.aButtons.push({
label: __('Siguiente'),
class: 'btn-moduloAvance',
show: (self.oContrato.definirPago || self.oContrato.horario_definido)
}
});
That's the Html:
<button ng-if="boton.show"
ng-repeat="boton in personaAndContrato.aButtons"
type="button"
ng-class="boton.class"
/>
I know that i'm assigning a boolean to the 'show' property, so it's impossible it changes because it's a simple type.
By the way I'm trying to assign a function to the 'show' property but i'm getting the following error:
self.aButtons.push({
label: __('Siguiente'),
class: 'btn-moduloAvance',
show: function () {
return (self.oContrato.definirPago || self.oContrato.horario_definido);
}
});
Html (edited):
<button ng-if="boton.show()"
ng-repeat="boton in personaAndContrato.aButtons"
type="button"
ng-class="boton.class"
/>
TypeError: v2.show is not a function
at fn (eval at compile (angular.js?version=alpha.1:14539), :4:240)
Some ideas? Does i'm missing or missunderstanding something?
Thanks in advance!
You can't have ng-repeat and ng-if in the same tag if ng-if refer to the inner variable of ng-repeat.
Just split it :
<div ng-repeat="boton in personaAndContrato.aButtons">
<button ng-if="boton.show()"
type="button"
ng-class="boton.class"
/>
</div>
Changing to ng-if="boton.show()" will do.

Angular JS - ng-repeat repeating old values

I am new to Angular JS. I have created a code in angular using app and controller. What I am tyring to do is to add name dynamically to a array when a button is clicked.
By default my array has two value passed. When i give an input and click the add button,it adds the string for the first time.
But when i give another input and click add again, the old string is replaced by the new string and the new string is added again.
Here is the piece of code on JSFiddle: http://jsfiddle.net/5DMjt/3680/
var demo= angular.module("demo",[]);
var simplecontroller = function($scope){
$scope.members = [{id:1,name:'prateek'},{id:2,name:'Ruchi'}];
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push(newmeber);
demo.controller(simplecontroller);
}
}
and here is the HTML Code:
<div ng-app="demo">
<div ng-controller="simplecontroller">
<ul>
<li ng-repeat="member in members">{{member.id}}-{{member.name}}</li>
</ul>
Name<input type="Text" ng-model="inputmember.name">
</br><h2>
{{inputmember}}
</h2>
<input type="button" value="Add" ng-click="addmember(inputmember)">
</div>
</div>
Please Help !
What i analyzed is that push function is passing the address that is why binding still exists.What u can do is pass the value instead like i did below-:
$scope.addmember = function(newmember){
newmember.id = $scope.members.length+1;
$scope.members.push({id:newmember.id,name:newmember.name});
demo.controller(simplecontroller);
}
Hope this solves your problem.Happy learning :)
You have two options.
Either you can reinitialize it every time what I would not recommend.
And the other one is to, pass the parameters with values.
$scope.members.push({id:newmember.id,name:newmember.name});
:)
See this updated fiddle: http://jsfiddle.net/5DMjt/3689/
Name<input type="Text" ng-model="newname">
This gives you a scope variable newname.
<input type="button" value="Add" ng-click="addmember()">
And addmember function uses this newname to create a new object and add it to the list:
$scope.addmember = function(){
var newmember = {};
newmember.id = $scope.members.length+1;
newmember.name = $scope.newname;
$scope.members.push(newmember);
}
You have a syntax error. See console error for more info.
Your variable inputmember is not defined anywhere.
Also you need to push to array new reference of the object, so the old one in array does not change each time you type value.
Here is a working version.
http://jsfiddle.net/a9zvgm8k/
$scope.addmember = function(newMember){
newMember.id = $scope.members.length+1;
$scope.members.push(angular.extend({}, newMember));
demo.controller(simplecontroller);
}
$scope.members = $scope.members.concat({id: newmember.id, name: newmember.name});
Solved : http://jsfiddle.net/5DMjt/3693/
Before pushing to $scope.members you need to create a new object and populate it with id and name from the input.

I'm having trouble writing a for loop in react.js

I'm new to programming and I'm learning Facebook's react.js. I found a website that has a tutorial which builds a "shopping cart" using react. I tried to modify it to add more items using a for loop but it keeps giving me "unexpected token }" errors followed by this error:
"Invariant Violation: FluxProduct.render(): A valid ReactComponent must be returned. You may have returned undefined, an array or some other invalid object."
I realize there is a similar question that was answered but it didn't help me.
There is quite a bit of code in this project but the particular spot I'm having trouble with looks like this:
render: function() {
var rows = [];
var ats = (this.props.selected.sku in this.props.cartitems) ?
this.props.selected.inventory - this.props.cartitems[this.props.selected.sku].quantity :
this.props.selected.inventory;
for (var i=0; i<2; i++){<div className="flux-products">
<img src={'img/' + this.props.product.image}/>
<div className="flux-products-detail">
<h1 className="name">{this.props.product.name}</h1>
<p className="description">{this.props.product.description}</p>
<p className="price">Price: ${this.props.selected.price}</p>
<select onChange={this.selectVariant}>
{this.props.product.variants.map(function(variant, index){
return (
<option key={index} value={index}>{variant.type}</option>
)
})}
</select>
<button type="button" onClick={this.addToCart} disabled={ats > 0 ? '' : 'disabled'}>
{ats > 0 ? 'Add To Cart' : 'Sold Out'}
</button>
</div>
</div>}
return ("flux-products-detail"
);
},
});
If you want/need the original code and the rest of the project I'd be more than happy to provide it.
It looks like you are trying to compose three components in the for loop. However the result of the for loop is not stored to a variable, and not rendered properly in the return function.
// Use a variable to store the result of the loop
return (
<div>
{myComponent}
</div>
)
In the case of using a loop to generate content for a React element, I usually formulate it something like this:
render: function() {
var items = [];
for(var i = 0; i < this.state.listOfItems.length; i++) {
items.push( <ItemComponent value={this.state.listOfItems[i].value} />
}
return ( <div> {items} </div>)
};
So what you need to do is return from render some JSX for react to Render. as #FelixKling said, JSX isn't magic, you're essentially just returning a bunch of React.createElement functions.

Categories