Save state of multiple Dynamic Components on ReactJS - javascript

Hi I have this component structure:
<ScheduleApp />
<ScheduleForm />
<TeamField />
My ScheduleApp contains a form called ScheduleForm and under this form I have a field where users can specify a number of teams and depends on the number the number of TeamField is created.
My form looks like this:
And what I wanted is to save all the teams' names under my ScheduleApp component. I can save all the other states with no problem, example: the No. of Teams field with no problem but I'm stuck on how to save the Team Name fields in an array.
Here is my poor attempt on saving the array but it looks like it saves all the keystrokes I've made probably because I triggered it onChange event.
How am I suppose to solve this problem and just save the dynamic components on the parent components' state?
Now here are my codes on jsfiddle for some reason I can't make it run on the site but will post it there for easier access.
Hope I made it clear. Any help would be much appreciated!

You are pushing the current content of text box into the array on every change/keystroke. Instead what you should do is text box 1 should only modify the first index in your array. And text box 2 should only modify second field in your array and so on. On each change, replace entire content with new content.
Or a cleaner approach would be to store a teams object. And send a team number field too in the on change handler against which you can store the team name.
<input className="form-control" type="text" ref="teamName"
onChange={this.handleChange.bind(null, 'team1')} /> // pass any index or string instead of team1
...
handleChange(teamIndex, teamName) {
let { teams } = this.state;
teams[teamIndex] = teamName;
this.setState({teams: teams};
}

Related

How to two-way bind a checkbox using Angular?

I currently have an accordion with a bunch of options in the form of checkboxes. The user can select the checkboxes as expected however, I want to already have some of those checkboxes checked depending on certain conditions. The issue is sometimes that is determined after the page has loaded. Below are simplified examples to demonstrate my code (my code is for work and would not be able to share due to confidentiality issues).
My HTML looks like this:
<div class="row">
<div "ngFor="let value of filteredPeople" >
<div>
<input type="checkbox" (click)="selectPeople(value)" [checked]="checkedPeople.get(value)">
{{ value }}
</div>
</div>
</div
My Javascript:
public checkPeople() {
this.selectedPeople.forEach(element => {
this.checkedPeople.set(element, true);
});
}
To explain some variables and methods:
Variables:
filterPeople - a string array of all possible people
checkedPeople - a map with a KVP of string (the people) and boolean (whether or not their checkbox is checked)
selectedPeople - a string array of people whose checkboxes I want already checked
Methods:
selectPeople - checks the corresponding checkbox when user clicks on it
checkPeople - a method called when I want the specific checkboxes checked (these specific checkboxes change based on other factors so I cannot hard code it)
For some reason my checkPeople method does not seem to select the expected checkboxes, I am not sure why but I have a feeling it is to do with the fact that I have used "[checked]" in the HTML and that it should be something else. Can someone clarify the issue for me and help me identify a fix? (Note: as the title suggests, I am using Angular)
Edit:
I have just debugged my code and added breakpoints, the checkedPeople map has the correct mapping of people to true for each of the elements in selectedPeople which shows that the checkPeople method is working as expected. Therefore the issue must be with the [checked] attribute if I'm not mistaken. I cannot see why it wouldn't work though.
You should use [ngModel]="checkedPeople.get(value)"
instead of [checked]="checkedPeople.get(value)"
to initialize the checkbox and
(change)="checkUncheckPeople(value, $event)"
to update the value when you check or uncheck it, where
checkUncheckPeople(value, e) {
this.checkedPeople.set(value, e.target.value);
}
So, in conclusion, your HTML input element will be:
<input
type="checkbox"
[ngModel]="checkedPeople.get(value)"
(change)="checkUncheckPeople(value, $event)"
/>
If you choose to use an object instead of a map then you can also directly use
[(ngModel)]="checkedPeople[value]"
to two-way bind the variable

Is there a way to run this script in a sequence?

For context I've made a script to assign a localstorage item based on what the user selects, this item may contain "S10" but could also contain many other values, for this example the user has selected "S10"
This has now stored into localstorage.
I have created this script that I have placed in each of the product grid includes, so this script will load multiple times for each product:
window.onload = function() {
const string = localStorage.getItem('MyfitmentList', JSON.stringify(myfitment) );
const attr = {{ product.metafields['fitment']['fitment'] | json }};
document.getElementById("fitment").innerHTML = (`${string.includes(attr) ? '✔' : 'not a fit' }`);
}
Each product grid also features this container <div id="fitment"></div>
The script above loads individually for each product grid card and has it's own seperate values for "attr". If "attr" doesn't contain "S10" (which the user previously selected) then it should show "not a fit", but if the product does contain "S10" then it should show the tick.
The problem I'm having is that this only works for the first script, on the first <div id="fitment"></div> container. I can see that each individual script has a different "attr" value which is good, but I don't know why only the first container is populated.
Each script should run individually and populate the "fitment" container within it's own product card. I'm a bit at a loss as to how to do it.
Also this is on Shopify - Someone below has recommended using a single script with a loop, but in that case how would I retrieve a unique "attr" value each time the script loops? this would still leave the question of how to populate each fitment container with the correct message for each product.
Any help would be really appreciated!

How can I write the code to append all of the items(XPages)?

I have many documents in Notes, all of the documents have a different form, like this picture :
(possibly like pic 1, pic 2, or pic 3)
How can I write the code in Xpages?
use the "computed field"? Or use the "input text"?
I used the "input text".But only for one item, not for all.
var doc = purchase.getDocument();
var A0 = doc.getItemValueString("DAY_A0");
if(A0 != 0){
return "Division processing";
}
If the form not only has one item, like the pics. How can I write the code to append all of the items?
I'm making the following assumptions here:
You have 10 fields in the document with numbers that might or might not be > 0
The 11th value (Total) shall be computed
You want to show one document at a time, not a list
You know how to add a data source to a page
Version 1:
Create a regular XPages form, use the wizard when adding the document data source. It now would show also the field with 0 values
Click on each ROW and change visibility property to computed (make sure you hit the row, not the cell or field) and add a visibility formula based on the field oof that row. Something like doc.DAY_A0 > 0
Add a computed field where you add the values of all 11 fields
done
Version 2:
in the page open event, get a handle on the document and compute a scoped variable that only contains the values you are interested in. Could be messy since you need a label (that is not your field name) and a value
Use a repeat control to render the values
Hope that helps

ReactJs - Add open and closing tag without syntax error

I have to generate a form from a JSON with materialize.
Generate the form components is not a problem but Im not able to create <span class="row"> to separate form inputs.
In my form component render method, Im iterating the json data and put every component (textfield, dropdown etc...) in an array and then return it.
render()
{
return <span className="row"> { this.buildForm() } </span>
}
This works greats but every input are printed inside a single row so I got problem when materialize has to manage input cols.
So I need to create dynamically the row span.
In my json I put a specific attributes call "rowstart" and "rowend" for every input field so I know if that input will start a new row or will close one.
For example if I have two input with cols = 6, the first one will have rowstart=true and the second one will have rowend=false
The problem came in render. I cant put an open or a close tag in the render.
if (attributes.rowstart)
{
formRender.push(<span className="row">);
}
switch(attributes['type'])
{
case 'string': formRender.push(<TextField .... />); break;
[...]
}
if (attributes.rowend)
{
formRender.push(</span>);
}
The render doesn't allow open/close tag because its now sure what happens in the next iteration so it can't say if the open tag will be really close.
Is there a way to solve it?
Searching on StackOverlow i found this post but its different from what I need. stack post
I suggest that you make rows a top level array elements and make every other inputs as children of rows
```
if (attributes.rowstart && attributes.children.length)
{
let row = (<span className="row">{attributes.children.map((input)=> <Input key={input.name} /> )}</span>);
formRender.push(row);
}
```

Click function in Django form

I have no idea how can I solve my problem. I have Django template with two models. I put these models in inlineformset_factory.
Example
DhcpConfigFormSet = inlineformset_factory(Dhcp, IPRange, extra=1)
and I displayed this form in template like this pictures
form http://sphotos-h.ak.fbcdn.net/hphotos-ak-prn1/601592_10151469446139596_1335258068_n.jpg
I want implement event, when I click on plus stick (marked field on pictures), show one more row (ip initial field, ip final field and delete check box).
I tried to do it on this way :
$(document).ready(function() {
$(".plusthick-left").click( function() {
var tr= $(".sort-table").find("tbody tr:last").length;
$(".sort-table").find("tbody tr:last").after($(".sort- table").find("tbody tr:last").clone())
});
but I have problem, because I just made copy of last row and took same attributes values?
My question is : How can I make new row, and set all attributes with values of last row increased by one.
For example:
<input type="text" id="id_ip_initial_0_ip_range">
This is field that generated form in template, and I want make field with id value like this:
<input type="text" id="id_ip_initial_1_ip_range">
How can I do it? :)

Categories

Resources