I have flow.js type definition as shown below:
export type Block = {
color: {
primary: Color,
secondary: Color,
},
font-size: '16px',
font-weight: '500',
};
And I would like to create an object with not all properties defined and another one with all fields required.
So second one:
const divv: Block = {
...all fields here
}
first one (just font-size):
const divv2: Block | any = {
font-size: '17px'
}
As you can see I've used
Block | any
To declare first one divv, but intellisense will hint me all divv2 properties, but it has only one of main Block type.
How to do it correctly?
Try $Shape
Copies the shape of the type supplied, but marks every field optional.
So, it'll be:
const divv2: $Shape<Block> = {
font-size: '17px'
}
Related
I am developing an application that has a quite sizeable amount of Queries and Mutation. Structures for data are often not complex, but there is plenty of them, so I have made myself a snippet, that generates the most common things repeating throughout them. This snippet also generates an input for mutations so it can be used for both simple and complex data structures. In quite a bit of instances, the input is just for adding a name. The API is supposed to be used mainly by my fronted, but after the app gets mature enough should be publicly available. Is doing this a problem in terms on conventions?
Sample of what I mean
/*=============================================
Types
=============================================*/
interface AddSampleSchemaInput {
input: AddSampleSchema
}
interface AddSampleSchema {
name: string
}
/*=============================================
Main
=============================================*/
export const SampleSchemaModule = {
typeDefs: gql`
type Mutation {
addSampleSchema(input: AddSampleSchemaInput): SampleSchema!
}
type SampleSchema {
_id: ID!
name: String!
}
input AddSampleSchemaInput {
name: String!
}
`
,
resolvers: {
Mutation: {
addSampleSchema: async (parents: any, args: AddSampleSchemaInput, context: GraphqlContext) => {
}
}
}
}
Sample of what I assume it should be.
/*=============================================
Main
=============================================*/
export const SampleSchemaModule = {
typeDefs: gql`
type Mutation {
addSampleSchema(name: String): SampleSchema!
}
type SampleSchema {
_id: ID!
name: String!
}
`
,
resolvers: {
Mutation: {
addSampleSchema: async (parents: any, args: { name: string }, context: GraphqlContext) => {
}
}
}
}
export default SampleSchemaModule
Would usage of the first code example be a problem. This means using input (input AddSampleSchemaInput), even if it were to contain just a single value (in this case name).
Or in other words is using input for every mutation a problem no matter the complexity.
Or the impact on frontent:
addDogBreed({
variables: {
input: {
name: "Retriever",
avergeHeight: 0.65
}
}
})
addDog({
variables: {
input: {
name: "Charlie"
}
}
})
// ======= VS =======
addDogBreed({
variables: {
input: {
name: "Retriever",
avergeHeight: 0.65
}
}
})
addDog({
variables: {
name: "Charlie"
}
})
In this case, is having the first one instead of the second one a problem?
Is having an input that only contains one key is something problematic?
No, on the contrary, it is something desirable in GraphQL. While nesting may sometimes seem superfluous, it is key in forward compatibility and extensibility of your schema. You should not have different conventions of how to design your mutation arguments depending on the number of inputs. If you always use an input object, you can easily deprecate existing fields or add new optional fields and stay compatible with all existing clients. If you were to completely change the shape of the mutation arguments just because you have an object with a single key, it would break compatibility.
I'm not seeing a problem that would drive you to
"only use GraphQL when dealing with Fetching / Get Data, and normal
REST API Request for mutating data (create, update, delete)."
Like #Bergi said. Plus you can provide your entity with multiple mutators some which can work like a PATCH or a PUT request.
Let's say I have this object:
const obj = {
ul: { padding: "20px 0", flex: 1 }, // <- there's a comma here!
li: { fontFamily: "'Lato'", lineHeight: "44px" }
}
Someone accidentally removes a comma separating two values:
const obj = {
ul: { padding: "20px 0", flex: 1 } // <-- oops! the comma that was here is gone...
li: { fontFamily: "'Lato'", lineHeight: "44px" }
}
Now eslint would say something like "Unexpected token", but will not be able to solve the error automatically with --fix. Is there a rule I can use to solve these type of issues automatically?
I've looked at rules like comma-dangle and object-property-newline but they don't seem to apply to this situation.
I have the following situation:
There are css rules inside of my JS var which looks like this:
"floating_icons": {
"main_color": "",
"phone_color": "",
"mail_color": "",
"whatsapp_color": ""
}
},
"style_css": ".pad-t { padding: 0 20px 0 20px;} .grey-t { color: rgba(127.765849375934, 127.765849375934, 127.765849375934, 0.217430264}"
}
},
"entity": {
"data": {
"data": {
And I need to apply 'style_css' it in my VueJS application. Unfortunatelly I didn't find any propriate solution for it.
Could you please help me out with it?
Binding Inline Styles guide for the Vuejs v2
The object syntax for v-bind:style is pretty straightforward - it looks almost like CSS, except it’s a JavaScript object. You can use either camelCase or kebab-case (use quotes with kebab-case) for the CSS property names:
<div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
data: {
activeColor: 'red',
fontSize: 30
}
It is often a good idea to bind to a style object directly so that the template is cleaner:
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
Again, the object syntax is often used in conjunction with computed properties that return objects.
Array Syntax
The array syntax for v-bind:style allows you to apply multiple style objects to the same element:
<div v-bind:style="[baseStyles, overridingStyles]"></div>
You should read the full guide at https://v2.vuejs.org/v2/guide/class-and-style.html
First of all let me introduce you to my project. I am desining a web application that will show some data about devices scattered around a country. To create this I used Vue.js and HighCharts (HighMaps for the map part). This is the result I have achieved now.
What I want to add now is the possibility for the end-user to click on a marked region and show all of the devices in that region. To do that I need the region's "ID", called code in HighMaps, to send a ajax request to my db and I would also like to make this new "div" a component so that I can use it freely in my application. I'll put a sketch image of what I mean (excuse me for my really bad paint skills :D):
The black lines are not important, what I would like to achieve is to show a new component besides the map (or wherever really). Next is my current code, I am using the one page, one component style so both template and script tags are in the same file and I omitted in the script tag all the unecessary things. Right now I just set up a div with curly brackets to update a variable on change, just to debug more easily. My main problem is that, in the plotOptions.series.point.events.click when I try to reference the this.foo variable it doesn't set it since the div doesn't update. I think that might be a scope issue but I wouldn't know where to start looking.
<template>
<div id="canvasContainer">
<highmaps :options="chartOptions"></highmaps>
<app-componentForDevices><app-componentForDevices>
<div>{{foo}}</div>
</div>
</template>
<script>
import HighCharts from 'vue-highcharts';
import json from '../map.json'
export default {
data: function () {
return {
foo: 'NO',
/* Map */
chartOptions: {
chart: {
map: json, // The map data is taken from the .json file imported above
},
plotOptions: {
series: {
point: {
events: {
click: function () {
this.foo='OK'
}
}
}
},
map: {
joinBy: ['hc-key', 'code'],
allAreas: false,
tooltip: {
headerFormat: '',
pointFormat: '{point.name}: <b>{series.name}</b>'
},
}
},
/* Zoom and move */
mapNavigation: {
enabled: true,
buttonOptions: {
verticalAlign: 'bottom'
}
},
series: [
{
allAreas: true,
showInLegend: false,
},
{
borderColor: '#a0451c',
cursor: 'pointer',
name: 'ERROR',
color: "red",
data: ['it-na', 'it-mi', 'it-mo', 'it-ud'].map(function (code) {
return {code: code};
}),
},
{
borderColor: '#a09e21',
cursor: 'pointer',
name: 'WARNING',
color: "yellow",
data: ['it-ts', 'it-av', 'it-ri'].map(function (code) {
return {code: code};
}),
},
{
borderColor: '#4ea02a',
cursor: 'pointer',
name: "OK",
color: "lightgreen",
data: ['it-pa', 'it-ve', 'it-bo', 'it-ta', 'it-pn'].map(function (code) {
return {code: code};
}),
},
],
}
}
}
}
</script>
<style scoped>
svg{
align-items: center;
}
Thanks in advance for the help. Cheers!
EDIT
I have just tried #icecream_hobbit 's suggestion and using a ECMA6 arrow function helped since now I can access the variable store in Vue but now I lost the access to the local arguments like this.name which made possibile for me to print the selected region. Any ideas? Am I missing something?
EDITv2
Thanks to #icecream_hobbit I have found a way to do what I wanted. You just need to add an object inside the parenthesis so that you can use this for the global variable and e for your mouse click event.
events: {
click: (e) => {
this.foo = 'OK'
this.foo = e.point.name
}
}
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
Until arrow functions, every new function defined its own this value
(a new object in the case of a constructor, undefined in strict mode
function calls, the base object if the function is called as an
"object method", etc.)
The this you were accessing did not belong to the Vue instance. You can use an arrow function () => {/*function body*/} to inherit the this of the Vue instance.
An arrow function expression has a shorter syntax than a function
expression and does not have its own this, arguments, super, or
new.target.
EDIT: For the added question of how do I do I get the Vue instance, and the object instance at the same time you can use a closure.
click: function(VueInstance){
return function() {
VueInstance.Foo = 'OK';
}(this)
}
In the view I need to generate the following classes:
<div class="comp comp--lock comp--red">Foo</div>
The lock and red are based on state, where the following values for color are possible:
comp--red, comp--yellow, comp--blue, and many other possible colors
Until now I was using a computed method to concatenate the class name based on data:
getCompClassName(){
return `comp ${this.isLock ? 'comp--lock' : ''} comp--${this.color}`
}
Looking at Vuejs documentation I see there is v-bind:class that should resolve this in a better way, the problem I have is how to solve the color interpolation, since I would need to declare all possible colors.
data: {
classObject: {
'comp--lock': this.isLock,
'comp--red': this.color === 'red',
'comp--blue': this.color === 'blue',
'comp--yellow': this.color === 'yellow'
}
}
Is there any way to solve this using v-bind:class that scales better without having to list all possibilities or should I use the computed method to interpolate the class name?
Could you not just use a computed?
computed: {
classObject() {
return {
'comp--lock': this.isLock,
[`comp--${this.color}`]: true
}
}
}
JSfiddle: https://jsfiddle.net/5sknyauz/5/
EDIT: you could actually do the same thing in data:
data() {
return {
classObject: {
'comp--lock': this.isLock,
[`comp--${this.color}`]: true
}
}
}