How to call validateFields of namePath of Arrayed object - antd

When I print form.getFieldsValue()
I get this form object:
{ books:
{
0:
{
title: "hello"
description: "this is a description"
}
1:
{
title: "hello 2"
description: "this is a description 2"
}
}
}
Within the form, I have functions that append new books to the form object.
{ books:
{
0: {...}
1: {...}
2: {...}
3: {...}
4: {...}
.
.
.
}
}
How do I call validate fields on all title fields which are required.
I tried various ways but am unable to validate all title fields in the form.
form.validateFields([ "books", "title" ]);
form.validateFields([ "books", "*", "title" ]);
form.validateFields([ "books", [], "title" ]);

form.validateFields([ "books", 0, "title" ]);
form.validateFields([ "books", 1, "title" ]);
form.validateFields([ "books", 2, "title" ]);
form.validateFields([ "books", 3, "title" ]);

Related

how to hide columns of antd data table for small devices(mobile view)?

If the table has five columns i want to display only 2 columns for mobile view
https://ant.design/components/table
you can keep columns in component state and dynamically filter the columns on window resize. Something like this
useEffect(() => {
window.addEventListener("resize", <callback function to update columns>);
// cleanup
return() => window.removeEventListener("resize");
});
Inside render method you need to declare columns with let and change them if window.innerWidth < 480 (I made it less then 500 px to be safe). By changing, I mean filtering from an array of columns only those columns that you want. The best way to filter is by key, because it's unique. This is how the code looks in react:
import React, { PureComponent } from "react";
import { Table } from "antd";
export default class MainPage extends PureComponent {
renderMobileTable = columns => {
return columns.filter(
column => column.key === "name" || column.key === "city"
);
};
render() {
const dataSource = [
{
key: "1",
name: "Mike",
lastName: "Willins",
age: 32,
address: "10 Downing Street",
city: "Chicago"
},
{
key: "2",
name: "John",
lastName: "Billards",
age: 42,
address: "5th Blvd",
city: "New York"
}
];
let columns = [
{
title: "Name",
dataIndex: "name",
key: "name"
},
{
title: "Last Name",
dataIndex: "lastName",
key: "lastName"
},
{
title: "Age",
dataIndex: "age",
key: "age"
},
{
title: "Address",
dataIndex: "address",
key: "address"
},
{
title: "City",
dataIndex: "city",
key: "city"
}
];
const isMobile = window.innerWidth < 500;
if (isMobile) {
columns = this.renderMobileTable(columns);
}
return <Table dataSource={dataSource} columns={columns} />;
}
}
For the source code you may refer to my repository on GitHub.
NOTE: if you are testing mobile view in Chrome Dev Tools, make sure you reload the page after resizing, as we put the logic into render method and the application has to be re-rendered or reloaded.
In antd v4 you can use column prop 'responsive'
const columns = [{
title: 'identification number',
dataIndex: 'ID',
responsive: ['sm'],
}]
https://ant.design/components/table/#Column

Is there a way to make api call when expanding table to show nested table?

In Ant Nested table - When expanding a row, I want to make an api call and get the data to show the nested table.
The function expandedRowRender, expects to return the nested table, it does not accept a promise.
How can I show a nested Ant table using ajax call?
I have tried to recreate the scenario for reference.
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Table } from "antd";
import reqwest from "reqwest";
const nestedColumns = [
{
title: "Name",
dataIndex: "name",
sorter: true,
render: name => `${name.first} ${name.last}`,
width: "20%"
},
{
title: "Gender",
dataIndex: "gender",
filters: [
{ text: "Male", value: "male" },
{ text: "Female", value: "female" }
],
width: "20%"
},
{
title: "Email",
dataIndex: "email"
}
];
class App extends React.Component {
state = {
data: []
};
fetch = (params = {}) => {
console.log("params:", params);
reqwest({
url: "https://randomuser.me/api",
method: "get",
data: {
results: 10,
...params
},
type: "json"
}).then(data => {
return (
<Table
columns={nestedColumns}
dataSource={data.results}
pagination={false}
/>
);
// this.setState({
// data: data.results
// });
});
};
expandedRowRender = () => {
this.fetch();
return <table columns={nestedColumns} dataSource={this.state.data} />;
};
render() {
const columns = [
{ title: "Name", dataIndex: "name", key: "name" },
{ title: "Platform", dataIndex: "platform", key: "platform" },
{ title: "Version", dataIndex: "version", key: "version" }
];
const data = [
{
key: 1,
name: "Screem",
platform: "iOS",
version: "10.3.4.5654"
}
];
return (
<Table
columns={columns}
dataSource={data}
pagination={false}
expandedRowRender={this.expandedRowRender}
/>
);
}
}
ReactDOM.render(<App />, document.getElementById("container"));
I try my level best to answer your question. Here is the reduced type of code and you can get an idea of how to do that.
In state,
state = {
data: null,
loading: false,
};
Here is your function to make API call,
fetch = (expanded, record) => {
axios.get(`put your api to load nested table`)
.then(res => {
const data = res.data;
this.setState({
...this.state.data,
data,
loading: true
})
}).catch(error => {
console.log(error, "error")
})
}
After that,
expandedRowRender=() => {
if(this.state.loading){
const nestedTableData = this.state.data.map(row => ({
key: row.id,
Id: row.id,
name: 'test',
gender: 'gender',
}))
const nestedColumns = [
{ title: "Name", dataIndex: "name", key: "name" },
{ title: "Gender", dataIndex: "gender", key: "gender" },
];
return <Table columns={nestedColumns} dataSource={nestedTableData } pagination={false} />
}
};
And put following code below return
<Table
className="components-table-demo-nested"
columns={columns}
dataSource={tableData}
expandable={{
expandedRowRender: this.expandedRowRender,
rowExpandable: record => true,
onExpand: this.fetch
}}
/>
I hope it may help you and let me know if it does. :)

MVC KENDO UI GRID - dynamic columns objects

Hi there im building a grid that have dynamic columns depending on the number of a specific object.. here's a example
public class Team
{
string name {get;set;}
List<members> memberslist {get;set;}
}
public class member{
string name {get;set;}
int goals {get;set;}
}
in the view:
#(Html.Kendo().Grid(Model.TeamList)
.Name("goalslist")
.Columns(columns =>
{
columns.Bound(team => team.name).Title("Team Name");
columns.Bound(team => team.memberslist);
}...
what i would like the result was something like this:
Team Name, John Smith Taylor Fernandez
Ajax       22      1     3
Milan      0      1      2
Any Ideia?! how its done will print object[object], i tried a lot of stufs but without sucess.. thanks
The easiest way to do this is through JSON. Convert your column list into json and pass it to the column, see below. At the very bottom you can see me pushing the columns to the grid. Below that you can see what the JSON itself looks like.
var gridJSON = {
dataSource: {
data: data,
schema: {
model: {} // the model gets filled in by the JSON coming from the database
},
pageSize: 20
},
height: 550,
groupable: false,
sortable: true,
resizable: true,
filterable: {
extra: false,
operators: {
string: {
startswith: "Starts with",
eq: "Is equal to",
neq: "Is not equal to"
}
}
},
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
toolbar: kendo.template($("#template").html())
};
gridJSON.columns = currentReport.JSON.columns;
gridJSON.dataSource.schema.model.fields = currentReport.JSON.fields;
Here is the JSON for the 'currentReport.JSON.columns'
"columns" : [{
"field" : "ReceiverID",
"title" : "Receiver ID"
}, {
"field" : "ReceiverBatchID",
"title" : "Batch ID"
}, {
"field" : "PoNumber",
"title" : "PO Number"
}, {
"field" : "ReceiverTransactionDate",
"title" : "Receiver Trans Date",
"format" : "{0: yyyy-MM-dd}"
}, {
"field" : "PrintingLocation",
"title" : "Location"
}, {
"field" : "VendorID",
"title" : "Vendor ID"
}, {
"field" : "InNemo",
"title" : "InNemo"
}, {
"field" : "Path",
"title" : "Path",
"encoded" : "true",
"template": "#=Path#",
"width" : "50"
}
]

mongodb/rails "exception: can't find special index: 2d for:"

i have a rails app where i have some problems with indexes. I search locations by name.
First i thought its a problem with the addresses.coords but iam not sure about it.
The relevant parts of the search controller:
#practices = Practice.published
#practices = #practices.where(:"addresses.country" => params[:country].upcase) if params[:country].present?
if params[:location].present? && latlng = get_coordinates
#practices = #practices.near_sphere(:"addresses.coords" => latlng).max_distance(:"addresses.coords" => get_distance )
end
# now find doctors based on resulting practices
#doctors = Doctor.published.in("organization_relations.practice_id" => #practices.distinct(:_id))
The complete crash log:
Moped::Errors::OperationFailure (The operation: #<Moped::Protocol::Command
#length=255
#request_id=646
#response_to=0
#op_code=2004
#flags=[]
#full_collection_name="um-contacts.$cmd"
#skip=0
#limit=-1
#selector={:distinct=>"practices", :key=>"_id", :query=>{"deleted_at"=>nil, "published_at"=>{"$lte"=>2012-11-05 15:17:14 UTC}, "addresses.country"=>"DE", "addresses.coords"=>{"$nearSphere"=>[13.4060912, 52.519171], "$maxDistance"=>0.01569612305760477}}}
#fields=nil>
failed with error 13038: "exception: can't find special index: 2d for: { deleted_at: null, published_at: { $lte: new Date(1352128634313) }, addresses.country: \"DE\", addresses.coords: { $nearSphere: [ 13.4060912, 52.519171 ], $maxDistance: 0.01569612305760477 } }"
See https://github.com/mongodb/mongo/blob/master/docs/errors.md
for details about this error.):
app/controllers/search_controller.rb:16:in `index'
Thats the result of the indexes, not sure how to query them from the addresses which are embedded via has_many.
> db.practices.getIndexes()
[
{
"v" : 1,
"key" : {
"_id" : 1
},
"ns" : "um-contacts.practices",
"name" : "_id_"
}
]
Help would be really appreciated!
Edit: Looks like the indexes for adresses.coords arent created,
db.system.indexes.find()
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.users", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.doctors", "name" : "_id_" }
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.collaborations", "name" : "_i
{ "v" : 1, "key" : { "_id" : 1 }, "ns" : "um-contacts.practices", "name" : "_id_" }
but should be created within the practice class:
class Practice
...
embeds_many :addresses, cascade_callbacks: true, as: :addressable
...
field :name, type: String
field :kind, type: String
field :slug, type: String
index({"addresses.coords" => '2d'}, { min: -180, max: 180, background: true })
index({name: 1})
index({slug: 1}, { unique: true })
...
Anyone have an idea why its failing?
try to re-create your indexes. for mongoid:
rake db:mongoid:create_indexes

How to join query in mongodb?

I have user document collection like this:
User {
id:"001"
name:"John",
age:30,
friends:["userId1","userId2","userId3"....]
}
A user has many friends, I have the following query in SQL:
select * from user where in (select friends from user where id=?) order by age
I would like to have something similar in MongoDB.
To have everything with just one query using the $lookup feature of the aggregation framework, try this :
db.User.aggregate(
[
// First step is to extract the "friends" field to work with the values
{
$unwind: "$friends"
},
// Lookup all the linked friends from the User collection
{
$lookup:
{
from: "User",
localField: "friends",
foreignField: "_id",
as: "friendsData"
}
},
// Sort the results by age
{
$sort: { 'friendsData.age': 1 }
},
// Get the results into a single array
{
$unwind: "$friendsData"
},
// Group the friends by user id
{
$group:
{
_id: "$_id",
friends: { $push: "$friends" },
friendsData: { $push: "$friendsData" }
}
}
]
)
Let's say the content of your User collection is the following:
{
"_id" : ObjectId("573b09e6322304d5e7c6256e"),
"name" : "John",
"age" : 30,
"friends" : [
"userId1",
"userId2",
"userId3"
]
}
{ "_id" : "userId1", "name" : "Derek", "age" : 34 }
{ "_id" : "userId2", "name" : "Homer", "age" : 44 }
{ "_id" : "userId3", "name" : "Bobby", "age" : 12 }
The result of the query will be:
{
"_id" : ObjectId("573b09e6322304d5e7c6256e"),
"friends" : [
"userId3",
"userId1",
"userId2"
],
"friendsData" : [
{
"_id" : "userId3",
"name" : "Bobby",
"age" : 12
},
{
"_id" : "userId1",
"name" : "Derek",
"age" : 34
},
{
"_id" : "userId2",
"name" : "Homer",
"age" : 44
}
]
}
Edit: this answer only applies to versions of MongoDb prior to v3.2.
You can't do what you want in just one query. You would have to first retrieve the list of friend user ids, then pass those ids to the second query to retrieve the documents and sort them by age.
var user = db.user.findOne({"id" : "001"}, {"friends": 1})
db.user.find( {"id" : {$in : user.friends }}).sort("age" : 1);
https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/
This is the doc for join query in mongodb , this is new feature from version 3.2.
So this will be helpful.
You can use in Moongoose JS .populate() and { populate : { path : 'field' } }.
Example:
Models:
mongoose.model('users', new Schema({
name:String,
status: true,
friends: [{type: Schema.Types.ObjectId, ref:'users'}],
posts: [{type: Schema.Types.ObjectId, ref:'posts'}],
}));
mongoose.model('posts', new Schema({
description: String,
comments: [{type: Schema.Types.ObjectId, ref:'comments'}],
}));
mongoose.model('comments', new Schema({
comment:String,
status: true
}));
If you want to see your friends' posts, you can use this.
Users.find(). //Collection 1
populate({path:'friends', //Collection 2
populate:{path:'posts' //Collection 3
}})
.exec();
If you want to see your friends' posts and also bring all the comments, you can use this and too, you can indentify the collection if this not find and the query is wrong.
Users.find(). //Collection 1
populate({path:'friends', //Collection 2
populate:{path:'posts', //Collection 3
populate:{path:'commets, model:Collection'//Collection 4 and more
}}})
.exec();
And to finish, if you want get only some fields of some Collection, you can use the propiertie select Example:
Users.find().
populate({path:'friends', select:'name status friends'
populate:{path:'comments'
}})
.exec();
MongoDB doesn't have joins, but in your case you can do:
db.coll.find({friends: userId}).sort({age: -1})
one kind of join a query in mongoDB, is ask at one collection for id that match , put ids in a list (idlist) , and do find using on other (or same) collection with $in : idlist
u = db.friends.find({"friends": ? }).toArray()
idlist= []
u.forEach(function(myDoc) { idlist.push(myDoc.id ); } )
db.friends.find({"id": {$in : idlist} } )
Only populate array friends.
User.findOne({ _id: "userId"})
.populate('friends')
.exec((err, user) => {
//do something
});
Result is same like this:
{
"_id" : "userId",
"name" : "John",
"age" : 30,
"friends" : [
{ "_id" : "userId1", "name" : "Derek", "age" : 34 }
{ "_id" : "userId2", "name" : "Homer", "age" : 44 }
{ "_id" : "userId3", "name" : "Bobby", "age" : 12 }
]
}
Same this: Mongoose - using Populate on an array of ObjectId
You can use playOrm to do what you want in one Query(with S-SQL Scalable SQL).
var p = db.sample1.find().limit(2) ,
h = [];
for (var i = 0; i < p.length(); i++)
{
h.push(p[i]['name']);
}
db.sample2.find( { 'doc_name': { $in : h } } );
it works for me.
You can do it in one go using mongo-join-query. Here is how it would look like:
const joinQuery = require("mongo-join-query");
joinQuery(
mongoose.models.User,
{
find: {},
populate: ["friends"],
sort: { age: 1 },
},
(err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);
The result will have your users ordered by age and all of the friends objects embedded.
How does it work?
Behind the scenes mongo-join-query will use your Mongoose schema to determine which models to join and will create an aggregation pipeline that will perform the join and the query.

Resources