ExtJS 5.0 Forms generated/driven by a store - extjs5

I would like to create a Form in ExtJS 5.0 completely based on a Store. Every store item represents a "line in the form". A "line" consists three or more form widgets.
Basically this is a search panel, where you define search conditions. Every condition consits of: FieldName selector, an operator selector, and a widget to write/select a condition operand. For example search for people with:
name starting with Joe (FieldName:name, operator:starting with, widget:textfield)
birtday before 1980.01.01. (FieldName:birthday, operator:before, widget:datepicker)
I get the conditions in JSON, and load them in a Store. I would like to dynamically generate the form based on this store, make modifications in the form, and ask the Store for a new JSON with the modifications (new conditions, etc).
I have problems with the first step: simply generate form widgets based on store content.
How can this be done?

I'm going to assume here that the JSON data represents a variety of dynamic data, and you can't simply use a pre-canned control like a grid, or a fixed form.
What you need to do is to make your own container class, which dynamically creates widgets based on the JSON content. You'll have to write this yourself, of course.
One extreme is to make your JSON content in the store be valid arguments to, say, Ext.widget - but that's probably not feasible, or even desirable.
For a more middling position, use the JSON data to determine, based on conditions, what widgets to add.
As a rough outline, you want something like this:
Ext.define('MyFormContainer', {
extend: 'Ext.form.FormPanel',
config: {
// A store or MixedCollection of JSON data objects, keyable by id.
formData: null
},
layout: 'vbox',
initComponent: function() {
this.callParent(arguments);
this.getFormData().each(this.addField, this)
},
addField: function(fieldData) {
var widgetConfig = this.buildWidgetConfig(fieldData);
this.add(widgetConfig);
},
buildWidgetConfig: function(fieldData) {
// The heart of the factory. You need a way to determine what sort of widget to make for
// the field. For the example config, a fieldset with three fields would probably be
// appropriate:
var fieldSet = { xtype: 'fieldset', layout: 'hbox' };
var items = [];
items[0] = { xtype: 'textfield', name: fieldData['FieldName'] };
// this would be a link to a custom widget to handle the operator. Or maybe you could
// just spit out text, if it's not meant to be alterable.
items[1] = { xtype: 'myoperator_' + fieldData['operator'], name: 'operator' };
items[2] = { xtype: fieldData['widget'], name: 'value' }
fieldSet.items = items;
return fieldSet;
}
})
This is a simple and contrived example, but it should (after you fill in the blanks, such as missing requires and the custom operator widgets) render a form based on the JSON data.
(I personally use this approach - with a great deal more sophistication that I can show in a simple example - to generate dynamic forms based on server-supplied form descriptions)

Related

How to display long string data from JSON as a list wise using react typescript

How to display long string data from JSON as a list wise if Description string is too long. How do i split or format description Using react and typescript .
I have below JSON data:
"options": [
{
"perkType": "GIFT_CARD",
"tierRewardId": "ff592a61-3e64-474e-a3e5-cb7c14cc73e1",
"perkDescription": "**Important details about the Perk:**\n* Perks are random additional items. These are not earned, but extra items given to customers outside of the spend levels.\n* See Terms and Conditions for exclusions and additional information.\n* [Terms & Conditions](www.xyz.net/TermsandConditions)",
},
{
"tierRewardId": "0aa6b029-3179-41dd-8726-78ca7e4bfe18",
"perkType": "TOOL_RENTAL",
"perkDescription": "**Important details about the Mik Perk:**\n* Mik Perks are random additional items. These are not earned, but extra items given to customers outside of the spend levels.\n* See Terms and Conditions for exclusions and additional information.\n* [Terms & Conditions](www.xyz.net/TermsandConditions)"
}
],
already i filter the data :
const optionGift = this.state.currentData.item.tierPerks[0].options.filter(
(list) => list.perkType === 'GIFT_CARD');
const optionGiftCard= optionGift.map((value)=> value );
const OptionRental = this.state.currentData.item.tierPerks[0].options.filter(
(list) => list.perkType === 'TOOL_RENTAL',);
const OptionRentalTool= OptionRental.map((value)=> value );
component tsx code :
<div> <ul className="YourPerkOption__modelParagraph">
<li>{props.optionGiftCard[0].perkDescription}</li></ul></div>
I am trying to display a list wise data into below format
if anybody can help please .
Custom Code
If I am understanding this correctly, the first line of the perkDescription is the title (**Important details about the Mik Perk:**) and the subsequent lines are bullet points. We need to break up the string into multiple string segments and then render them to the DOM through JSX. Let's make that into it's own reusable component.
The only prop that we need is the string text.
interface PerkDescriptionProps {
text: string;
}
Our component breaks that text into an array of lines with the string.Prototype.split() method. We store the first element of the array to a variable title and the rest of the lines to another variable bullets using spread syntax. We then loop through the bullets array and put each one inside of a li element.
export const PerkDescription = ({ text }: PerkDescriptionProps) => {
const lines = text.split("\n");
const [title, ...bullets] = lines;
return (
<div className="perkDescription">
<div className="perkDescriptionTitle">{title}</div>
<ul className="perkDescriptionList">
{bullets.map((line, i) => (
<li key={i}>{line}</li>
))}
</ul>
</div>
);
};
You would call it like this:
<PerkDescription text={optionGiftCard[0].perkDescription} />
But I think you should create a Perk component that uses this PerkDescription!
I am not dealing with the asterisks here so you'll still see them in the HTML output. Are you using some some of package to parse markdown syntax?
Markdown Parsing
Your JSON is using a standardized markdown syntax to denote the list. There are already packages out there which can handle the bulleted list as well as turning the link into an a element and adding the bold styling to the title.
Using react-markdown, all you need to do is put your text inside of a ReactMarkdown component.
import ReactMarkdown from 'react-markdown'
<ReactMarkdown>{optionGiftCard[0].perkDescription}</ReactMarkdown>
You could use a RegEx to split perkDescription into an array and then map that array.

How can I pass parameters to getter in Sequelize model?

What I'm doing:
I'm reading csv which contains data like townships, religions and so on. In the csv, they are text values. But of course in my table in the database, they are foreign_key. So to insert those, I need to map those text values to id.
It is possible to get the id like below.
const { townshipId } = await models.Township.findOne({
where: { name: township },
attributes: ["townshipId"],
raw: true,
});
The problem:
But the problem what I think is that those findOne(s) will be populated in my entire method because I have like 50 other properties besides township.
What I'm trying
I'm trying to pass township-name to a getter method, expecting its equivalent townshipId.
I found out that it is possible to use getter and setter in sequelize. But I don't find how to pass parameters to those.
My question
Am I trying the correct way to import the csv data? How can I use getters (and setters) with parameters in sequelize?
Maybe if you want to exclude columns from the result, you pass the "attributes" field like:
attributes: { exclude: ['field1','field2'] }
This way you wont show the columns "field1" and "field2" in the result.

Updating Data within a unique randomly generated ID/KEY in firebase using HTML

function updateFirebase(){
const fb=firebase.database().ref()
//get field values
author = document.getElementById('uname').value
user_email = document.getElementById('umail').value
data = {author, user_email}
//update database
fb.child('Article/').update(data);
}
</script>
I have problem with my code. I want to update the data inside a table named "Article". Article has generated items with a unique key/id and each key has its own content. Lets say I want to be able to edit the "author" or change the "title", the problem is they each have a randomly generated key/id that I cant access. for example that "-LS39kReBHrKGqNj7h_". I can only save the data inside the "Article" tree but I cant change the "author" or the "title". How do i get a workaround this so I can change those properties?
Here is how my firebase looks like
It depends whether you have the record reference on the frontend before update or not (whether you have fetched it before you are trying to update it).
But generally, you have two options
You can store the key reference as an "id" field on the object.
To achieve that, you need two step process when creating the record at the first place
// Creates a new record in DB and returns it to you. Now you can get the "key"
const newRecord = firebase.database().ref('TABLE_NAME_REF').push();
newRecord.set({
id: newRecord.key
...
});
This is great if you fetch the list of records on the frontend and then you want to update one of them. Then you can just build the ref path like this
fb.child('Article/' + record.id ).update(data); // where record is the prefetched thing
You need to find the element based on its fields first. And once you have it, you can update it right away.
To achieve this, you can simply do something like:
firebase.database()
.ref('TABLE_NAME_REF') // let's say 'Article'
.orderByChild('RECORD_KEY') // Let's say 'author'
.equalTo('KEY_VALUE') // let's say 'zoranm'
.limitToFirst(1)
.once("value")
.then(res => {
// You need to loop, it always returns an array
res.forEach(record => {
console.log(record.key); // Here you get access to the "key"
fb.child('Article/' + record.key ).update(data); // This is your code pasted here
})
})

CSV Parser through angularJS

I am building a CSV file parser through node and Angular . so basically a user upload a csv file , on my server side which is node the csv file is traversed and parsed using node-csv
. This works fine and it returns me an array of object based on csv file given as input , Now on angular end I need to display two table one is csv file data itself and another is cross tabulation analysis. I am facing problem while rendering data, so for a table like
I am getting parse responce as
For cross tabulation we need data in a tabular form as
I have a object array which I need to manipulate in best possible way so as to make easily render on html page . I am not getting a way how to do calculation on data I get so as to store cross tabulation result .Any idea on how should I approach .
data json is :
[{"Sample #":"1","Gender":"Female","Handedness;":"Right-handed;"},{"Sample #":"2","Gender":"Male","Handedness;":"Left-handed;"},{"Sample #":"3","Gender":"Female","Handedness;":"Right-handed;"},{"Sample #":"4","Gender":"Male","Handedness;":"Right-handed;"},{"Sample #":"5","Gender":"Male","Handedness;":"Left-handed;"},{"Sample #":"6","Gender":"Male","Handedness;":"Right-handed;"},{"Sample #":"7","Gender":"Female","Handedness;":"Right-handed;"},{"Sample #":"8","Gender":"Female","Handedness;":"Left-handed;"},{"Sample #":"9","Gender":"Male","Handedness;":"Right-handed;"},{"Sample #":";"}
There are many ways you can do this and since you have not been very specific on the usage, I will go with the simplest one.
Assuming you have an object structure such as this:
[
{gender: 'female', handdness: 'lefthanded', id: 1},
{gender: 'male', handdness: 'lefthanded', id: 2},
{gender: 'female', handdness: 'righthanded', id: 3},
{gender: 'female', handdness: 'lefthanded', id: 4},
{gender: 'female', handdness: 'righthanded', id: 5}
]
and in your controller you have exposed this with something like:
$scope.members = [the above array of objects];
and you want to display the total of female members of this object, you could filter this in your html
{{(members | filter:{gender:'female'}).length}}
Now, if you are going to make this a table it will obviously make some ugly and unreadable html so especially if you are going to repeat using this, it would be a good case for making a directive and repeat it anywhere, with the prerequisite of providing a scope object named tabData (or whatever you wish) in your parent scope
.directive('tabbed', function () {
return {
restrict: 'E',
template: '<table><tr><td>{{(tabData | filter:{gender:"female"}).length}}</td></tr><td>{{(tabData | filter:{handedness:"lefthanded"}).length}}</td></table>'
}
});
You would use this in your html like so:
<tabbed></tabbed>
And there are ofcourse many ways to improve this as you wish.
This is more of a general data structure/JS question than Angular related.
Functional helpers from Lo-dash come in very handy here:
_(data) // Create a chainable object from the data to execute functions with
.groupBy('Gender') // Group the data by its `Gender` attribute
// map these groups, using `mapValues` so the named `Gender` keys persist
.mapValues(function(gender) {
// Create named count objects for all handednesses
var counts = _.countBy(gender, 'Handedness');
// Calculate the total of all handednesses by summing
// all the values of this named object
counts.Total = _(counts)
.values()
.reduce(function(sum, num) { return sum + num });
// Return this named count object -- this is what each gender will map to
return counts;
}).value(); // get the value of the chain
No need to worry about for-loops or anything of the sort, and this code also works without any changes for more than two genders (even for more than two handednesses - think of the aliens and the ambidextrous). If you aren't sure exactly what's happening, it should be easy enough to pick apart the single steps and their result values of this code example.
Calculating the total row for all genders will work in a similar manner.

Iterating through couchbase keys without a view

In couchbase, I was wondering if there was a way - WITHOUT using a view - to iterate through database keys. The admin interface appears to do this, but maybe its doing something special. What I'd like to is make a call like this to retrieve an array of keys:
$result = $cb->get("KEY_ALBERT", "KEY_FRED");
having the result be an array [KEY_ALEX, KEY_BOB, KEY_DOGBERT]
Again, I don't want to use a view unless there's no alternative. Doesn't look like its possible, but since the "view documents" in the admin appears to do this, I thought i'd double-check. I'm using the php interface if that matters.
Based on your comments, the only way is to create a simple view that emit only the id as par of the key:
function(doc, meta) {
emit( meta.id );
}
With this view you will be able to create query with the various options you need :
- pagination, range, ...
Note: you talk about the Administration Console, the console use an "internal view" that is similar to what I have written above (but not optimized)
I don't know about how couchbase admin works, but there are two options. First option is to store your docs as linked list, one doc have property (key) that points to another doc.
docs = [
{
id: "doc_C",
data: "somedata",
prev: "doc_B",
next: "doc_D"
},
{
id: "doc_D",
data: "somedata",
prev: "doc_C",
next: "doc_E"
}
]
The second approach is to use sequential id. You should have one doc that contain sequence and increment it on each add. It would be something like this:
docs = [
{
id: "doc_1",
data: "somedata"
},
{
id: "doc_2",
data: "somedata"
}
...
]
In this way you can do "range requests". To do this you form array of keys on server side:
[doc_1, doc_2 .... doc_N]and execute multiget query. Here is also a link to another example
The couchbase PHP sdk does support multiget requests. For a list of keys it will return an array of documents.
getMulti(array $ids, array $cas, int $flags) : array
http://www.couchbase.com/autodocs/couchbase-php-client-1.1.5/classes/Couchbase.html#method_getMulti