How would you render this simple UI using React js? - api

I am new to React and I want to render the UI shown in the picture.
Description:
The UI consists of two main components the sidenav and the display container. The side nav shows the title and the number of questions/answers pairs in for that given tab. When the user clicks on a tab of the side nav, the display container outputs the selected tab as a title with the questions/answers pairs, see api.
EX: the user clicks tab2 on the side nav, the display container will show
Tab2
Question C
Answer to Question C
Question D
Answer to Question D
Question E
Answer to Question E
And the side nav tab 2 will display 3, since there are 3 question/answer pairs.
[IMG]http://imgur.com/fR4DVoP[/IMG]
http://imgur.com/fR4DVoP
The data will be fetched from an api in the json format
[ { 'Tab1' : [
{
'question':'QuestionA',
'answer':'Answer to Question A'
},
{
'question':'QuestionB',
'answer':'Answer to Question B'
}
],
'Tab2' : [
{
'question':'QuestionC',
'answer':'Answer to Question C'
},
{
'question':'QuestionD',
'answer':'Answer to Question D'
},
{
'question': 'QuestionE',
'answer': 'Answer to Question E'
}
]
//... tab3, tab4, an so on...
}

Had you read reac-router tutorial ? if not here's the link.
Please read it careful, after that, you will have a good understanding how to acomplish your requirement using react router Links in the easy way.
Or checkout this repo Starter Kit as starting point

Related

Object reactivity of complex object

I have an issue with complex object reactivity.
I've read everything I can on stack to find a way to solve it, but nothing works. I've looked at object reactvity and array caveats on vuejs, but not working either.
So I'm asking some help please.
Let me explain the project:
I have 2 columns :
- on the left side, I CRUD my content
- on the right side, I display the results
I have my object, and I'm adding new elements on its "blocks" property (text, images, etc...)
[
{
"uid": 1573224607087,
"animation": "animationName",
"background": {
"bckColor": "#ff55ee",
...
},
"blocks": []
}
]
On click event, I add a new element via this method. Everything is ok, I can CRUD a block.
addBloc(el) {
if (el.type == "text") {
const datasA = {
type: "text",
uid: Date.now(),
slideId: this.pagination.currentPage,
content: el.content,
css: {
color: "#373737",
...
},
...
};
this.slides[this.pagination.currentPage].blocks.push(datasA);
this.$bus.$emit("newElement", datasA);
}
To modify the order of my elements on the display side, I added a drag and drop module to move my block on my DOM tree. Smooth dnd
The problem is, when I drang&drop my element, my object is updated correctly, but the DOM isn't. The dragged element goes back to its initial position.
What is strange, when I try to modify my block (the one I dragged), it modifies the other one.
I'me adding a small video, so you can see what's happening.
Small animation to show you what's going on
I add some more explainations.
I use event bus to communicate between my components, and the right side is using its own object!
I don't know how I can solve this issue.
Tell me if you need more information.
Thank you all !
EDIT 1 :
I added an id to each block to see what happens when I start Drag&Drop. ==> blocks are moving correctly. The problem is not coming from the method onDrop() but from my nested components if I understand well. They don't update. I'm going to search for this new issue.
I've added a new gif to show what's going on.
This is the nested structure
TheSidebar.vue => top container
<Container
:data-index="i"
#drop="onDrop(i,$event)"
:get-child-payload="itemIndex => getChildPayload(i, itemIndex)"
lock-axis="y"
>
<Draggable
v-show="pagination.currentPage === i"
v-for="(input, index) in slides[i].blocks"
:key="index.uid"
:id="'slideBlocksContainer'+index"
class="item"
>
blockId #{{input.uid}}
<AppContainer
v-if="input.type == 'text'"
:blocType="input.type"
:placeholder="input.content"
:id="index"
:slideId="i"
></AppContainer>
</Draggable>
</Container>
Then I have my AppContainer.vue file, which is a top level. In this I have the specific elements of each input type
And I have AppElement.vue file, which is common elements, I can use everywhere
Something like this
TheSidebar
--AppContainer
----AppElement
Know I don't know yet, how to force vue to update AppContainer.vue and AppElement.vue
EDIT 2 :
As suggested in this article I've changed the key of the component and now , when I drag and drop my elements, they stay where they are dropped.
What I see also, is that the AppElement inputs, are related to their own AppContainer. So everything is ok now, but I don't know if it is best practices.
The issue appears to be that the Smooth dnd library you are using is not updating the array of blocks that you are passing to it, it is likely making a copy of the array internally. So when you change the position of the blocks by dragging and dropping, you are not changing your blocks array, just the internal copy.
Looking at the Smooth dnd documentation, if you wanted to access the modified array you could try using the drag-end event handler:
onDragEnd (dragResult) {
const { isSource, payload, willAcceptDrop } = dragResult
}

Put an event on a table row in vuejs

Hi i have been looking for a simple answer to this question but cant seem to find one i have the spatie table plugin for my vue app which looks like this.
<table-component id="table1" :data="[
{ firstName: 'John', birthday: '04/10/1940', songs: 72 },
{ firstName: 'Paul', birthday: '18/06/1942', songs: 70 },
{ firstName: 'George', birthday: '25/02/1943', songs: 22 },
{ firstName: 'Ringo', birthday: '07/07/1940', songs: 2 },
]" sort-by="songs" sort-order="asc">
<table-column show="firstName" label="First name"></table-column>
<table-column show="songs" label="Songs" data-type="numeric"></table-column>
<table-column show="birthday" label="Birthday" :filterable="false" data-type="date:DD/MM/YYYY"></table-column>
</table-component>
I want to create a method that when you click a table row it pushes my router to a different page and passes the table row information to the next router page
this.$router.push('/analytic-one');
Any help or advice would be appreciated thank you.
There are a couple of ways you could solve this.
But for the clicks themselves, in the Documentation for spatie table component, which was updated after this question was asked.
The table-component currently emits one custom event:
#rowClick: is fired when a row is clicked. Receives the row data as it's event payload.
Which tells us that the row data is returned in the payload, so we can do
<table-component #rowClick="myHandlerMethod" ....
And in our methods object
methods: {
myHandlerMethod: function (clickedItem) {
console.log(clickedItem)
}
}
And for sending the data to a new page, you could solve it in many ways.
You could use vuex to temporarily store the table information after clicking the table row, then push the router to the new page and fetch the data from the vuex state again.
Or you could use something like $router.push('route?artistId=' + clickedItem.id) and then do an ajax call to fetch data for that column again when the user lands on the new page, which is the clean way to do this. (this is pseudo code, look into vue router for the proper way of binding variables to the route.) This assumes you have an id in your data-set.
Or you could opt for using a modal instead, then you could do something like
this.selectedItem = clickedItem in the click handler.
Hope that gives you a general direction.

unable to edit data on container coming fron a store in Sencha Touch Architect

I'm using Sencha Architect 2.1
I have an Store and a Container, but how can I render the data from the store using the container?
I created a 1 minute video explaining the problem:
http://www.youtube.com/watch?v=_HpR9h80D94
In other words this is what I want to do in Secha Designer 2:
data: ordersStoreId.getData(),
Compleate:
xtype: 'container',
title: 'MyContainer6',
iconCls: 'info',
data: ordersStoreId.getData(),
tpl: [
'Testing: {status}'
]
Any idea? Thanks! :)
So this looks like a bug. I guess one way to work around this issue is to add the show listener to your container and then you can dynamically pull in data from your store.
listeners: {
show: function(this, opts){
this.setData( Ext.getStore('yourStore').getData() );
}
}
So in Architect:
1) Select your container
2) In your config window add an Event Bindings by clicking the + icon and choose Basic Event Binding
3) Choose the event name show like I suggested. You will then be presented with an editable code view where you can put your code. ex:
this.setData( Ext.getStore('yourStore').getData() );
Hope this helps.

In extjs how to store selected radio buttons option

I am working in extjs+Yii. In extjs i am creating multiple choice question paper of 20 questions. These questions i am retriving from Yii framework. So in extjs i am having code as=
View=
Question.js
Ext.define('Balaee.view.question.Question',
{
extend:'Ext.form.Panel',
requires:[
'Balaee.view.question.QuestionView'
],
id:'QuestionId',
alias:'widget.question',
title:'Question',
height:180,
items:[
{
xtype:'questionView',
},
],//end of items square
buttons:[
{
xtype:'button',
fieldLabel:'Vote',
name:'vote',
formBind:true,
text:'submit',
action:'voteAction',
}
]
});
QuestionView.js
Ext.define('Balaee.view.question.QuestionView',
{
extend:'Ext.view.View',
id:'QuestionViewId',
alias:'widget.questionView',
store:'Question',
config:
{
tpl:'<tpl for=".">'+
'<div id="main">'+
'</br>'+
'<b>Question :-</b> {question}</br>'+
//'<p>-------------------------------------------</p>'+
'<tpl for="options">'+ // interrogate the kids property within the data
'<p>&nbsp&nbsp<input type="radio" name="opt" >&nbsp{option} </p>'+
'</tpl></p>'+
'</div>'+
'</tpl>',
itemSelector:'div.main',
}
});
So i am having view which is displaying question and its options as radio buttons. i am displaying 20 questions. At the end its having submit button. On the click of submit button,i want to display result. To calculate result i need to store user's selected options of all question in store of extjs in order to calculate result. So how to store all questions selected option in extjs?
Are you asking how to place the form's radio button values into an ad-hoc Ext data store?

sencha touch - custom html template ported from another framework

Previous attempt at this app was done in jqtouch and this effect worked perfectly. Im having a really hard time wrapping my head on how best to do this with sencha touch.
My situation is best described in this image
This is just one item that should populate a carousel so reusing it with different data is paramount (no hard coded html).
thank you
Finally solved it thought I should update it here
Ext.define('mobuy.view.myCarousel', {
extend: 'Ext.carousel.Carousel',
alias: 'widget.myCarousel',
config: {
myitems: 0,
},
updateMyItems: function(newItem) {
var localCarouselItems = [];
Ext.each(newItems, function(item){
localCarouselItems.push({
xtype:'localItem',
data:item.data
});
});
this.setItems(localCarouselItems);
this.setActiveItem(0);
}
})
what this does is basically create an array of new items of type localItem from the store when one calls setMyItems and sets the data (to be used with xtemplate or whatever) for each of those items.
If anybody needs more details please ask and I'll update my answer.