hello guys i am fetching data from my api and i try to set a search bar like this :
import React, { Component } from "react";
import ProductsIndex from "./search_bar";
class SearchBar extends Component {
constructor(props) {
super(props);
this.state = { term: "" };
this.onInputChange = this.onInputChange.bind(this);
this.onFormSubmit = this.onFormSubmit.bind(this);
}
onInputChange(event) {
this.setState({ term: event.target.value });
}
onFormSubmit(event) {
event.preventDefault();
ProductsIndex.renderProducts(this.state.term)
// this.props.fetchWeather(this.state.term);
this.setState({ term: "" });
}
render() {
return (
<form onSubmit={this.onFormSubmit} className="input-group">
<input
placeholder="Get a five-day forecast in your favorite cities"
className="form-control"
value={this.state.term}
onChange={this.onInputChange}
/>
<span className="input-group-btn">
<button type="submit" className="btn btn-secondary">Submit</button>
</span>
</form>
);
}
}
export default SearchBar;
In my onSubmit function try to call my function renderProducts from my class ProductsIndex here :
class ProductsIndex extends Component {
componentDidMount() {
this.props.fetchProducts();
}
renderProducts(term) {
return _.map(this.props.products, product => {
if(product.name==term) {
return (
<tr key={product.name}>
<td>{product.name}</td>
<td>{product.product_category.name}</td>
<td>{product.price}</td>
</tr>
);
}
});
}
render(){
return(
<div>
<table className="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Name</th>
<th>Category</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{this.renderProducts()}
</tbody>
</table>
</div>
);
}
}
function mapStateToProps(state) {
return {products: state.products}
}
export default connect(mapStateToProps, {fetchProducts})
(ProductsIndex);
But that is doesn't work i get this error : Uncaught TypeError: _search_bar2.default.renderProducts is not a function
Thanks you for your help
The short answer is: ProductsIndex.prototype.renderProducts
The correct answer is: the state of terms should be owned by a component higher up in the hierarchy. SearchBar triggers a state change in the parent component and it trickles down to ProductIndex. You already probably have a component suitable for this in your hierarchy, but here is how it may look if you add one explicitly for this purpose.
export class SharedParent extends React.Component {
constructor() {
super();
this.state = {
term: ""
};
//I use this style for methods, you can also use fat arrows to ensure 'this' is properly set
this.setTerm = this.setTerm.bind(this);
}
setTerm(term) {
//beware current best practice is to pass a fucntion
//not an object to setState
this.setState({ term });
}
render() {
return [
<ProductIndex key="a" term={this.state.term} {...this.props.productProps} />,
<SearchBar key="b" setTerm={this.setTerm} {...this.props.searchProps}/>
];
}
}
PS: I would suggest also using Redux or another state management solution. You can't go wrong with Redux though.
Related
I'm trying to get data from person field in SharePoint. My code always returns 8 rows (its correct) but at items that consists of Person it returns [object Obejct].
enter image description here
export interface SPUser {
Pracovnik: String;
}
.
.
private getListData(): void {
this._getListData().then((response) => {
this._renderList(response);
});
}
private _renderList(items: SPUser[]): void {
let html: string = '<table class="TFtable" border=1 width=100% style="border-collapse: collapse;">';
html += `<th>Title</th>`;
items.forEach((item: SPUser) => {
if(item.Pracovnik != null) {
html += `
<tr> <td>${item.Pracovnik}</td> </tr>
`};
});
html += `</table>`;
const listContainer: Element = this.domElement.querySelector('#spGetListItems');
listContainer.innerHTML = html;
}
private async _getListData(): Promise<SPUser[]> {
return pnp.sp.web.lists.getByTitle("org_struktura").items.select("Pracovnik/ID").expand("Pracovnik").get().then((response) => {
return response;
});
}
public render(): void {
this.domElement.innerHTML = `
<div class="parentContainer" style="background-color: lightgrey">
<div style="background-color: lightgrey" id="spGetListItems" />
</div>
`;
this.getListData();
}
Any idea what is wrong please?
Sample demo to map SharePoint list item to a Type object.
export interface IReactItem{
Id:number,
Title:string,
Description:string,
User:{ID:number,EMail:string},
enableEdit:boolean
}
private async _getListData(): Promise<IReactItem[]> {
return pnp.sp.web.lists.getByTitle("TestList").items.select("Id,Title,Description,User/ID,User/EMail").expand("User").get().then((response:IReactItem[]) => {
return response;
});
}
My question is, I want to print table in reactJS. I have already use axios to get data from django views and I got a response. But, I don't know who to set this data in table format. I have used Table of react-bootstrap. And I am very new in ReactJS.
My Code Snippet is:
change(){
axios.get('http://127.0.0.1:8000/users/')
.then(function (response) {
console.log("in user",response.data[0].id);
this.setState({
id: response.data[0].id,
username: response.data[0].username,
email: response.data[0].email,
});
})
.catch(function (error) {
console.log(error);
});
}
But Now how to use this id, username, and email in "tbody" tag? Please Guide me. Thanks.
Inside your render function where you used react-bootstrap Component. Just use
<tbody>
<tr>
<td>{this.state.id}</td>
<td>{this.state.username}</td>
<td>{this.state.email}</td>
</tr>
</tbody>
You are actually only saving to state one element, you should save to state the resulting array of data.
import React, { Component } from 'react';
import Axios from 'axios';
export default class example extends Component {
constructor(props) {
super(props);
this.state = {
users: [],
};
}
componentDidMount() {
Axios.get('http://127.0.0.1:8000/users/')
.then(function (response) {
this.setState({
users: response.data,
});
})
.catch(function (error) {
console.log(error);
});
}
render() {
const { users } = this.state;
return users.lenght > 0 ? (
<table striped>
<thead>
<tr>
<td>ID</td>
<td>Username</td>
<td>Email</td>
</tr>
</thead>
<tbody>
{users.map((user) => {
return (
<tr key={user.id}>
<td>{user.id}</td>
<td>{user.username}</td>
<td>{user.email}</td>
</tr>
);
})}
</tbody>
</table>
) : (
<h1>No data available!</h1>
);
}
}
Model: 'Category'
Subclass: 'Workflow'
I am trying to display the different 'Workflows' available for each 'Category' but I am receiving this error >>
Uncaught Error: Nothing handled the event 'createWorkflow'.
Here's some code
VpcYeoman.Category = DS.Model.extend({
permittype: DS.attr('string'),
isCompleted: DS.attr('boolean'),
classNameBindings: ['isAdministrator']
});
VpcYeoman.Workflow = VpcYeoman.Category.extend({
workflowtype: DS.attr('string')
})
VpcYeoman.Category.FIXTURES = [
{
id: 1,
permittype:'Building'
},
{
id: 2,
permittype:'Electrical'
},
{
id: 3,
permittype:'Zoning'
},
{
id: 4,
permittype:'Fire'
}
];
I'm also a little stumped on how to make FIXTURES for this subclass. I attempted recreating VpcYeoman.Workflow.FIXTURES = [id & workflowType examples], but it didn't display.
Category.hbs
<div class="department-header">
<div class="user-header">
Category: {{permittype}}
</div>
</div>
<table class="table table-hover table-responsive">
<thead>
<tr class="people-list">
<td><h4>Workflow Type</h4></td>
</tr>
</thead>
<table>
{{#each workflows}}
<tr>
<td>
{{workflowtype}}
</td>
</tr>
{{/each}}
</table>
<div class="input-bar">
<img src="images/lightning-icon-edited.png" class="input-icon">
{{input type="text" value=newWorkflowtype placeholder="Create a workflow and press enter" action="createWorkflow"}}
</div>
&&
VpcYeoman.CategoriesController = Ember.ArrayController.extend({
actions: {
createCategory: function () {
var permittype = this.get('newPermittype');
if (!permittype.trim()) {return;}
var category = this.store.createRecord('category', {
permittype: permittype
});
this.set('newPermittype', '');
category.save();
},
createWorkflow: function () {
var workflowtype = this.get('newWorkflowtype');
if (!workflowtype.trim()) {return;}
var workflow = this.store.createRecord('workflow', {
workflowtype: workflowtype
});
this.set('newWorkflowtype', '');
workflow.save();
}
}
});
&&
VpcYeoman.CategoriesRoute = Ember.Route.extend({
model: function() {
return this.store.find('category');
},
setupController:function(controller, model){
this._super(controller, model);
controller.set('workflows', this.store.find('workflow'));
}
});
VpcYeoman.CategoryRoute = Ember.Route.extend({
});
I'm assuming that you have a categories and category routes/templates based on the differently named things up there.
actions go the the particular route's controller Category then the route's route Category then up the routes Categories, Application
It looks like you are setting the workflows on the Categories controller, but trying to use it in the Category template
I am getting this error in the console:
Assertion failed: The value that #each loops over must be an Array. You passed (generated home controller)
Uncaught TypeError: Object [object Object] has no method 'addArrayObserver'
My HTML looks like this:
<script type="text/x-handlebars">
<div id="top-panel">
<h1>{{{title}}}</h1>
</div>
<div id="wrapper">
<div id="content">
{{outlet}}
</div>
</div>
</script>
<script type="text/x-handlebars" id="home">
<table>
<thead>
<tr>
<th>Id</th>
<th>Foo</th>
<th>Bar</th>
<th>Foo Bar</th>
</tr>
</thead>
<tbody>
{{#each}}
<tr>
<td>{{itemId}}</td>
<td>foo</td>
<td>foo</td>
<td>foo</td>
</tr>
{{/each}}
</tbody>
</table>
</script>
I have defined the home route like this:
App.Router.map(function () {
this.resource("home", { path: "/" });
});
App.HomeRoute = Ember.Route.extend({
model: function () {
$.getJSON("mocks/items.json", function (items) {
console.log(items);
return items;
});
}
});
The console.log(items) logs an array of objects in the console so that is correct. I don't know why the each loop in the home template is not working then.
Found out where the problem is. I forgot to return the promise object inside the route:
App.HomeRoute = Ember.Route.extend({
model: function () {
$.getJSON("mocks/items.json", function (items) {
console.log(items);
return items;
});
}
});
Should be:
App.HomeRoute = Ember.Route.extend({
model: function () {
return $.getJSON("mocks/items.json", function (items) {
console.log(items);
return items;
});
}
});
I'm new to ember.js which seems to be very interesting but hard/difficult to learn cause there are so many ways to solve a programming problem.
I try to code a very simple app but don't know how...
The app show at the top in a table all customers with an id received from a json file (testin local) and on click on the id there will be a json-request to receive detailed infos to the customer.
The problem is, that I receive detailed data but can't display it in a template under the overview template...
Can some one help me...!?
Greets
Christian [from germany]
Here's some code-snippets I got till now...
APP.JS
App.Search = Ember.Object.extend();
App.Search.reopenClass({
all: function() {
// console.log('Search.reopenClass all');
return $.getJSON("json/kunden_suchen.json").then(function(response) {
var items = [];
response.Konto.forEach(function(child) {
// console.log(child);
var item = new App.item();
item.set('content', child);
item.set('nr', child.nr);
item.set('name1', child.name1);
item.set('name2', child.name2);
item.set('plz', child.anschrift.plz);
item.set('anschrift', child.anschrift);
items.push(item);
});
return items;
});
}
});
App.SearchRoute = Ember.Route.extend({
model: function() {
// console.log('SearchRoute model');
return App.Search.all();
},
events: {
details: function() {
console.log('SearchRoute detail');
return App.Details.all();
}
}
});
App.Details= Ember.Object.extend();
App.Details.reopenClass({
all: function() {
// console.log('Search.reopenClass all');
// return $.getJSON("json/kunden_suchen.json").then(function(response) {
return $.getJSON("json/customer.json").then(function(response) {
var items = [];
response.Konto.forEach(function(child) {
console.log(child);
var item = new App.item();
item.set('content', child);
item.set('nr', child.nr);
items.push(item);
});
return items;
});
}
});
index.html
<script type="text/x-handlebars" data-template-name="items">
<div style="width: 80%; margin: auto;">
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Name1</th>
<th>nr</th>
</tr>
</thead>
<tbody>
{{#each item in model}}
<tr class="info">
<td> {{ item.content.name1 }} </td>
<td> {{ item.content.id}} </td>
{{/each}}
</tbody>
</table>
</div>
</script>
Arrays in ember are augmented, e.g. it's prototype, so for your arrays to be binding aware and thus live updating your templates when the data asynchronously arrives you can't just use vanilla push(...) but pushObject(...) instead.
So try to change every occurrence of push to pushObject
...
items.pushObject(item);
...
Hope it helps.
Greets Alex [From Spain] :)