Format formly form field - angularjs

I want to format a field when the data finally updates the model. The number usually comes back with a decimal point so what I want to be able to do is format it to no decimal point number (parseNumber function does that).
e.g. vm.model.total = 34.54
I want to format this number to 34 on the fly.
I can't make it work...
vm.fields = [
{
className: 'row',
fieldGroup: [
{
className: 'col-xs-12',
key: 'total',
type: 'input',
templateOptions: {
wrapperClass: 'row',
labelClass: 'col-xs-9 col-sm-3',
dataClass: 'col-xs-3 col-sm-2 col-sm-offset-right-7',
label: 'Total',
disabled: true
},
formatters: [parseNumber(vm.model.total, 0)]
}
]
}
];

Your example does not match the examples in the documentation
Your argument to formatters field is incorrect. That field is expecting a function, NOT THE RESULT of the function, which is what you have defined here.
You should either use an anonymous function or a named function:
formatters: [function(value){ return parseNumber(value, 0); }]
or
formatters: [removeDecimal]
//...
function removeDecimal(value) {
return parseNumber(value, 0)
}
This is a working example from their own documentation which I have added a formatter to the first name field: https://jsbin.com/hapuyefico/1/edit?html,js,output

Related

Custom label on d3plus-react Treemap

I have to customize the label of a d3plus-react series, the customization will be pretty close to the original one with the label and the percentage but instead of taking the name from the id as the original does I will take it from another field of the object (name).
The object has this structure:
id: string
name: string
value: number
parent: string
and that's my Treemap config:
const methods = {
data: propsData,
groupBy: ['parent', 'id'],
size: 'value',
tooltipConfig: {
title: (d) => `${d.parent} - <span>${d.name}</span>`,
},
legend: true,
shapeConfig: {
label: (d) => {
console.log(d);
return [d.name];
},
},
};
The problem is that I don't know how to modify the label of the tile without touching the shared percentage, I've searched through the docs but I haven't found nothing relevant.
Does anyone know if there are some official methods for doing this or I'll have to do it myself?
Desired result
I've found out that you have access also to the percentage, the code will be as following
const methods = {
data: propsData,
groupBy: ['parent', 'id'],
size: 'value',
tooltipConfig: {
title: (d) => `${d.parent} - <span>${d.name}</span>`,
},
legend: true,
shapeConfig: {
label: (d) => {
return [d.customProperty, d.percentage];
},
},
}
Instead of the name I've used a custom property previously added to the data object so the series have the desired name

How can I access all elements with a particular attribute in graphQL?

I have some json data in file called countryData.json structured as so:
{
"info":"success",
"stats":
[{
"id":"1",
"name":"USA",
"type":"WEST"
},
//...
I'm using graphQL to access this data. I have created an object type in the schema for countries using the following:
const CountryType = new GraphQLObjectType({
name: "Country",
fields: () => ({
id: { type: GraphQLID },
name: { type: GraphQLString },
type: { type: GraphQLString },
})
});
I want to write a query that will allow me to access all of the elements of this array that have a certain "name" value(There can be multiple with the same name). I've written the following query, but it only returns the first match in the array:
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { type: { name: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
}
}
});
The "_" comes from const _ = require('lodash');
Also, how can I just get every single item in the array?
I have not recreated the code, therefore I can not check if it would be executed correctly. This is code, that should work in my opinion (without trying). If you want to return array of elements you need to implement https://lodash.com/docs/#filter. Filter will return all objects from stats, which match the argument name. This will return correctly inside resolver function, however, your schema needs adjustments to be able to return array of countries.
You need probably rewrite the arguments as follows as this is probably not correct. You can check out how queries or mutation arguments can be defined https://github.com/atherosai/express-graphql-demo/blob/feature/2-json-as-an-argument-for-graphql-mutations-and-queries/server/graphql/users/userMutations.js. I would rewrite it as follows to have argument "name"
args: { name: { type: GraphQLString } }
You need to add GraphQLList modifier, which defines, that you want to return array of CountryTypes from this query. The correct code should look something like this
const RootQuery = new GraphQLObjectType({
name:"RootQueryType",
fields:{
country: {
type: CountryType,
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.find(countryData.stats, {name: args.name});
}
},
countries: {
type: new GraphQLList(CountryType),
args: { name: { type: GraphQLString } },
resolve(parent, args){
return _.filter(countryData.stats, {name: args.name});
}
}
}
});
Now if you call query countries, you should be able to retrieve what you are expecting. I hope that it helps. If you need some further explanation, I made the article on implementing lists/arrays in GraphQL schema as I saw that many people struggle with similar issues. You can check it out here https://graphqlmastery.com/blog/graphql-list-how-to-use-arrays-in-graphql-schema
Edit: As for the question "how to retrieve every object". You can modify the code in resolver function in a way, that if the name argument is not specified you would not filter countries at all. This way you can have both cases in single query "countries".

Bitmask to boolean conversion in the model

I have a model that receives int bitmasks from the backend:
{"user": 7, "group":5, "other":1}
and I now want to show a form with checkboxes like this:
user: [X] read [X] write [X] execute
group: [X] read [ ] write [X] execute
other: [ ] read [ ] write [X] execute
where user can toggle on or off and then the updated bitmask is sent back to the server in a store.sync operation.
I know how to make and align the checkboxes, but ExtJS checkboxes in a form bind to boolean values through a correlation between the checkbox name and the model field name, and not to parts of bitmask.
So I have to convert back and forth between the bitmask int and a bunch of booleans. How would I implement that in a reusable manner?
I think the checkbox group component is a good candidate to render your checkboxes and also to implement the conversion logic.
Here is a reusable component to do the two-way conversion of bitmasks:
Ext.define('Fiddle.Bitmask', {
extend: 'Ext.form.CheckboxGroup',
xtype: 'fiddlebitmask',
isFormField: true,
columns: 3,
items: [{
boxLabel: 'Read',
name: 'read',
inputValue: 1,
excludeForm: true,
uncheckedValue: 0
}, {
boxLabel: 'Write',
name: 'write',
inputValue: 1,
excludeForm: true,
uncheckedValue: 0
}, {
boxLabel: 'Execute',
name: 'exec',
inputValue: 1,
excludeForm: true,
uncheckedValue: 0
}],
getModelData: function () {
let obj = {};
obj[this.name] = this.getValue();
return obj;
},
setValue: function (value) {
if (value) {
var binary = Ext.String.leftPad((value).toString(2), 3, '0');
value = {
read: Number(binary[0]),
write: Number(binary[1]),
exec: Number(binary[2])
};
}
this.callParent([value]);
},
getValue: function () {
var value = this.callParent();
var binary = `${value['read']||0}${value['write']||0}${value['exec']||0}`
return parseInt(binary, 2);
}
});
And the working fiddle: https://fiddle.sencha.com/#view/editor&fiddle/2clg
edit Component completed with getModelData implementation to support usage with form.getValues/form.updateRecord.
What version of Ext are you using? If your version supports ViewModels then I would do the conversion in the ViewModel and bind it to the view.
There is the convert and calculate config on fields as well but they are converting in one way only.

Ionic 2 / 3: Number Input from Alert

I'm using Ionic 3.x on macOS.
I have the following issue:
I have an array containing a number and an array of names.
table: { number: number, names: string[] } = {
number: 0,
names: ['']
};
I want to set the number of the array using an input for the user. I stumbled upon the AlertController.
I have written the following function thing to add a number:
addTable(){
let prompt = this.alertCtrl.create({
title: 'Add Table',
subTitle: 'Enter the table number',
inputs: [{
name: 'tableNumber',
placeholder: 'Number',
type: 'number'
}],
buttons: [
{
text: 'Cancel'
},
{
text: 'Add',
handler: data => {
//this.tables.push(data);
this.table.number = data;
}
}
]
});
prompt.present();
}
But this always sets table.number to object [object]. If I write it as this.table.number = +data; it has the value NaN. The push version also doesn't work.
How do I set table.number to a number that the user put in?
The name of the input
name: 'tableNumber'
gets added as a property name to the resulting object. You can access it like this:
handler: data => {
this.table.number = data.tableNumber;
}

Using angular-translate with formly in a select form

I'm trying to use angular-translate to translate the data from a select input on a form made formly, but I can't make it work properly.
Basically, when using angular-translate for other types of input, I would have to do something like
'templateOptions.label': '"NAME" | translate',
'templateOptions.placeholder': '"NAME" | translate'
following this pattern, I've tried to put my data like this:
"templateOptions.options": [
{
"name": "{{ 'OPT1' | translate }}",
"id": 1
},
{
"name": "{{ 'OPT2' | translate }}",
"id": 2
}
]
But that gives me nothing on the dropdown menu. Can someone give me any directions here?
The complete code can be found on the link http://output.jsbin.com/horawaqaki/
Thanks for the help!
In this case you can use $translate service inside your controller. This service can return you translated values, but it is asynchronous operation. Because of this you should add some flag in your controller in order to show form only when you receive this translations (in this example I'm going to use vm.areFieldGenerated and then show/hide form and element with ng-if).
So, basically you should pass an array of localization keys and $translate service will return you the following object:
{
'NAME': 'Name',
'OPT1': 'Working!',
'OPT2': 'Working indeed!'
}
And after that you are able to use this value to localize your field title or options.
Your function for generating fields and assigned translated values to the options will look like this:
// variable assignment
vm.env = getEnv();
vm.model = {};
vm.options = {formState: {}};
vm.areFieldsGenerated = false;
generateFields();
// function definition
function generateFields() {
$translate(['NAME', 'OPT1', 'OPT2']).then(function(translationData) {
vm.fields = [
{
key: 'item',
type: 'select',
templateOptions: {
valueProp: 'id',
labelProp: 'name',
options: [
{name:'Not working!', id: 1},
{name:'Not working indeed!', id: 2}
]
},
expressionProperties: {
'templateOptions.label': transationData['NAME'],
'templateOptions.options': [
{
name: translationData['OPT1'],
id:1
},
{
name: translationData['OPT2'],
id:2
}
]
}
}
];
vm.originalFields = angular.copy(vm.fields);
vm.areFieldsGenerated = true;
});
}
I've created working example here.
More examples with $translate on angular-translate.github.io.

Resources