All of the examples I've found online only show how to create single level accordion, like this:
-parent1
-child1
-parent2
-child2
I need to create dynamic accordion that has multiple nested parents, like this:
-parent
-subparent1
-subparent2
...
-subparentN
- child
My data comes in this format:
// first object in response is always considered to be the PARENT,
last one is always CHILD, and those in between are SUBPARENTS
// number of SUBPARENTS is not constant
"parents": [
{
"id": "583", // TOP LEVEL PARENT
"label": "PARENT",
"description": "irrelevant description here, i only need to show label for parents"
},
{
"id": "593",
"label": "SUBPARENT1",
"description": "..."
},
{
"id": "594",
"label": "SUBPARENT2",
"description": "..."
},
{
"id": "604",
"label": "SUBPARENT3",
"description": "..."
},
{
"id": "605", // CHILD
"label": "CHILD LABEL",
"description": "FEW LINES OF DESCRIPTION I NEED TO DISPLAY"
}
]
Based on the component you linked, it might be a good idea to have each as its own array (parent, subparent, an child label), and render its own collapsible.
For parent, have an accordion inside _renderContent function, and have that accordion be filled with its subparent. For subparent with child, have their _renderContent be filled with its child's content as well.
For parent's renderContent (see its sections props)
_renderContent = section => {
return (
<View style={styles.content}>
<Accordion
sections={SUBPARENT_SECTIONS}
activeSections={this.state.activeSections}
renderSectionTitle={this._renderSectionTitle}
renderHeader={this._renderHeader}
renderContent={this._renderContent}
onChange={this._updateSections}
/>
</View>
);
};
For subparent, do the same thing with its child label. It's probably a good idea not to have them on the same array, so you don't confuse them together.
Related
I have the following array of words that compose some sentences:
let words = [
{
"start_time": "2.54",
"end_time": "3.28",
"alternatives": [
{
"confidence": "1.0",
"content": "Hello",
"__typename": "Alternative"
}
],
"type": "pronunciation",
"__typename": "TranscriptItems"
},
{
"start_time": null,
"end_time": null,
"alternatives": [
{
"confidence": "0.0",
"content": ".",
"__typename": "Alternative"
}
],
"type": "punctuation",
"__typename": "TranscriptItems"
},
{
"start_time": "3.29",
"end_time": "3.52",
"alternatives": [
{
"confidence": "1.0",
"content": "This",
"__typename": "Alternative"
}
],
"type": "pronunciation",
"__typename": "TranscriptItems"
}
]
Also i have this variable that contain an array of snippets selected from the words above:
const snippets = [{ start: 2.54, end: 4.00, id: 12, snippetTitle: "This is the title" }];
Right now I am showing the words by doing a simple .map and returning <span>s for every word.
What I am trying to accomplish is the following: if the span i am currently on is between a snippet from snippets variable, wrap it in another div/component so i can highlight it.
So instead of <span>Hello</span>.<span>This</span> i would be able to wrap both spans in a new wrapper component or div like <Highlight><span>Hello</span>.<span>This</span></Highlight>
You can do something like this using the reduce function:
export default myComponent = () => {
let cache = [];
return (
<>
{myArray.reduce((accumulator, currentValue) => {
if(!isInSnippets(currentValue)){
if(cache.length > 0){ // return the cached value for highlight
accumulator.push( (<Highlight>
{cache.map((elt, i) => <span key={i}>{elt}</span>)
</Highlight>));
cache = [];
}
accumulator.push(<span>{currentValue}</span>);
}
else cache.push(currentValue);
return accumulator;
}}
</>
)
}
The accumulator will contain an array of jsx elements. The regular elements will be contained in spans, while the Highlighted elements will be contained all together within a Highlight component.
We store the Highlighted elements in a cache variable. When we face a "regular" element, we check if there is something in the cache. If there is, we put them all in a highlight element, and add it to the cache. Then we add the "current" regular value.
So, I have to split a json, but I don't know how. I need that the name of a category goes shows in a tab. Here's a example of my json:
"tabs": [
{
"General": [
{
"created_at": "2019-11-29 11:32:11",
"name":'Test 1'
},
{
"created_at": "2019-11-29 11:32:11",
"name":'Test 2'
},
]
},
{
"One More": [
{
"created_at": "2019-11-29 15:01:55",
"name": "Test 3"
}
]
}
]
The tab code I understand (is like this: https://react-bootstrap.github.io/components/tabs/), my problem is just show "General" or "One More" on the tab name, and the name changes... I know is a silly question, but I can't find a good explanation.
Thanks for the help!
Following the docs to render one tab for each key of tabs
<Tabs defaultActiveKey="profile" id="uncontrolled-tab-example">
{
Object.keys(tabs).map(key =>(
<Tab title={key} key={key}>
Foo
</Tab>
))
}
</Tabs>
Object.keys(myObject) will provide you an array of strings representing each property of the original object
I need help because I'm losing my mind haha ...
I have the main array products with this (it's just a sample) :
[
{
"from": "country",
"maker": "name of maker",
"id": "1969",
"image": "image.jpg",
"label": "355",
"name": "name of product",
"price": "12.90",
"subscriber_price": "8.90",
"url_path": "url",
"occasion": null,
"colour": "31",
"origin": "397",
},
{
"from": "country",
"maker": "name of maker",
"id": "2043",
"image": "image.jpg",
"label": "362",
"name": "name of product",
"price": "24.90",
"subscriber_price": "24.90",
"url_path": "url",
"occasion": "51,376,155,39",
"colour": "31",
"origin": "395"
}
]
I'm working this the Picker Component. So, what I'm doing is :
I have a Picker to select products with their "colour".. then I have another one to filter the selected products (only with colour:31 for example) with their "origin" and finally I want to filter them through their "label" ...
The fact is I have 3 Pickers, 3 functions to select them and it's working but the problem is I'm erasing with a setState my render of "displayProducts". So, when I have selected the 3 options, I can't go back..
For example, I choose "colour:31" with "origin:397" and "label:355" .. I can't go back and tell : finally I want "origin:395" because it doesn't exist anymore, etc... and one "colour" can have different "label, origin, ..."
I'm doing something like this but it's only available for ONE option and not multiple options and without keeping a solution to find again my filtered products :
onChangeGetOrigin(originValue) {
this.setState(() => ({
activeOrigin: originValue,
displayProducts: this.state.displayProducts.filter(product => product.origin == originValue)
}));
}
Do anyone can understand what I'm saying ? :-D
You can maintain two arrays. One contains the complete list of products and the other one is a derived array after applying the filters. You can use the derived list for display and original array for selection.
I am trying to retrieve item values from an object containing several items. The object is an array object. I am puzzled by only being able to retrive the first item and its values in each array instead of all items. Can anybody tell me what I am missing here.
The array object example:
{ "ITEM 1": [
{
"id": 123,
"name": "item1a"
},
{
"id": 234,
"name": "item1b"
},
{
"id": 345,
"name": "item1c"
}
],
"ITEM 2": [
{
"id": 456,
"name": "item2a"
},
{
"id": 567,
"name": "item2b"
},
{
"id": 678,
"name": "item2c"
}],
}
I have data within the new element and on debugging see that loop flows correctly but for some reason only the first item is rendered.
My code that is wrapped in an html element is as follows:
{ Object.keys(this.props.data).map(function (key) {
var list = component.props.data[key];
for (i = 0; i < facetParent.length; i++) {
var item = list[i];
return (
<CheckBox
key={item.id}
data={item}
name={item.name} />
)
}}, this)}
Any suggestions are much appreciated.
The return function immediately terminates the function execution. That is why you only get the first item. Depending on what version of react you use, you should create 2 arrays and join them before rendering
I'm completely rebuilding my website (originally hacked together with Wordpress) using Laravel and AngularJS. It's been a massive learning experience and I think I'm nearly there but for one problem.
On my site 'schemes' (or courses) are made up of 'units' which are made up of 'lessons'. Retrieving this data is fine, using Eloquent I retrieve valid JSON like this made up example...
[
{
"id": "1", //Scheme Id
"title": "Sports",
"description": "This is a Sports course!",
"units": [
{
"id": "1",
"title": "Tennis",
"lessons": [
{
"id": "6",
"title": "Serving"
},
{
"id": "7",
"title": "Hitting the ball with top-spin"
}
]
},
{
"id": "2",
"title": "Athletics",
"lessons": [
{
"id": "1",
"title": "Long Jump"
},
{
"id": "2",
"title": "Hurdling Technique"
}
]
},
{
"id": "4",
"title": "Golf",
"lessons": [
{
"id": "4",
"title": "Pitching"
},
{
"id": "5",
"title": "Putting"
}
]
}
]
}
....
]
Separately I have a simple array of completed lesson ids for a particular user like this...
[2, 6, 8, 9] ///User has completed lessons with ids of 2,6,8 and 9
In my view I'm using nested ng-repeat loops like so...
...
<div ng-controller="SchemesController">
<div ng-repeat="scheme in schemes">
<h1>{{scheme.title}}</h1>
<div ng-repeat="unit in scheme.units">
<h3>{{unit.title}}</h3>
<div ng-repeat="lesson in unit.lessons">
<div>{{lesson.title}}: {{status}}</div>
</div>
</div>
</div>
</div><!--[end of ng-controller="SchemesController"]-->
....
SchemesController (v simple!) looks like this...
var app = angular.module('schemesApp', []);
app.controller('SchemesController', function($scope){
$scope.schemes=jsonData;
});
The problem is I have no idea how to populate the {{status}} field which I want to state simply 'Complete' or 'Incomplete. I investigated whether I could somehow add this info to my original array like this...
"lessons": [
{
"id": "6",
"title": "Serving",
"status": "Complete" //populated somehow
},
{
"id": "7",
"title": "Hitting the ball with top-spin",
}
]
but I got nowhere slowly. Is there a way to do this (I've played around with underscore.js and felt this could help?).
Or do I populate {{status}} from creating and calling a javascript function?!?
ANY help that anyone could offer would be incredible. I'm a school teacher and for some sadistic reason I find a bit of programming/web design a fun use of my spare time so I apologise if this is a stupid question. THANKS in advance!!!
btw if anyone has a better 'title' for this question then please let me know.
I'm assuming you don't need to persist the status back to the database...
This is where you're having the problem:
<div>{{lesson.title}}: {{status}}</div>
You really don't need to store the status in your data model, because it's just used for presentation purposes.
Let's say your array of completed lessons is defined like this:
$scope.completedLessons = [1, 2, 3, 4, 5] // Or however you'd assign it
You need to create a function in your scope like this:
$scope.isLessonCompleted = function(lessonId) {
return $scope.completedLessons.indexOf(lessonId) > -1;
};
Then you need to change the html from above to this:
<div>{{lesson.title}}: {{isLessonCompleted(lesson.id) && 'Complete' || 'Incomplete'}}</div>
If lessons are also a model and each lesson should have a status, which isn't a column/field in your table but is something you'll add logic to determine, you could add a custom model accessor by adding the following to your models/Lesson.php:
// Append custom accessor attributes
protected $appends = ['status'];
public function getStatusAttribute() {
// Add logic here
return 'Complete';
}
This way, when you use Eloquent to retrieve your data, you'll also see a status attribute as part of the object, so you could then access it as usual $lesson->status (PHP) or lesson.status (JS).
For more information, see the official Laravel documentation on accessors and mutators