We've built an app with Vue.js and Firebase where jobs is a node in our db. When we add an event, we want to include the jobs available for that event. On our "Add Event" layout, I've included checkboxes of all the jobs in the DB. We want to be able to select the relevant jobs.
The way it is set up, it works great if you only check one job, but we often need to include 5-10 jobs.
How can I change the code so that I can select multiple jobs at once?
<v-list-tile v-for="(job, index) in jobs" :key="job.title">
<v-list-tile-content>
<v-checkbox
:key="job.title"
:label="job.title"
:value="job.title"
v-model="checkboxes[index].checked">
</v-checkbox>
</v-list-tile-content>
</v-list-tile>
...
export default {
data () {
return {
title: '',
description: '',
startDate: '',
endDate: '',
checkboxes: [],
jobs:[],
...
computed: {
items () {
this.checkboxes = this.jobs.map(job => {
return {
checked:false
}
})
return this.jobs
},
jobs () {
return this.jobs
}
},
... vuex:
created () {
this.jobs = this.$store.getters.loadedJobs
},
Use the index from v-for to keep track of which boxes are checked. Something like the following should get you started:
<v-list-tile v-for="(job, index) in items" :key="job.title">
<v-list-tile-content>
<v-checkbox :value="job.title"
:key="job.title"
:label="job.title"
v-model="checkboxes[index].checked">
</v-checkbox>
</v-list-tile-content>
</v-list-tile>
export default {
data () {
return {
checkboxes: [],
jobs: []
}
},
computed: {
items () {
this.checkboxes = this.jobs.map(job => {
return {
checked: false
}
})
return this.jobs
}
},
created() {
this.$nextTick(() => {
this.jobs = [
{
L9cWVNxnQMfumDkUxxp: {
title: "job 1"
}
},
{
L9cWVNxnQMfumDkUxp: {
title: "job 2"
}
},
{
L9cWVNxnQMfumDkxxp: {
title: "job 3"
}
}]
})
}
}
Working fiddle:
https://jsfiddle.net/6yarqagf/5/
Related
I need to figure out how to update the onFetchMore method. I have a page, on this page I see 10 elements and, when I click on the "Show more" button, I have to add another 10 elements, etc. So I must add to the existing ones of the others.
When I click, the warning pops up in the console (The updateQuery callback for fetchMore is deprecated, and will be removed in the next major version of Apollo Client.)
const { loading, error, data, networkStatus, fetchMore } = useQuery(sezioneByUuid, {
variables: { slug: slug || sezione, limit: 10 },
errorPolicy: 'all',
fetchPolicy: 'network-only',
partialRefetch: true,
notifyOnNetworkStatusChange: true,
skip: false,
});
const onFetchMore = useCallback(() => {
const {
page: {
apertura,
block: {
set: {
pagedItems: { items },
},
},
},
} = data;
fetchMore({
variables: {
limit: 10,
exclude: [apertura.set.first.uuid].concat(
items.map((articolo) => {
const { uuid } = articolo;
return uuid;
}),
),
},
updateQuery: (prev, { fetchMoreResult }) => {
if (!fetchMoreResult) return prev;
// prev
const {
mktg,
page: {
__typename: pageTypeName,
slug,
uuid,
section,
seo,
apertura,
block: {
page,
__typename: blockTypeName,
uuid: blockUuid,
set: {
__typename: setTypeName,
uuid: setUuid,
pagedItems: { uuid: pagedItemsUuid, __typename: pagedItemsTypeName, items: oldItems },
},
},
},
} = prev;
// fetch more contents
const { items: newItems, hasNext, excluded } = fetchMoreResult.page.block.set.pagedItems;
return {
page: {
uuid,
__typename: pageTypeName,
slug,
block: {
page,
uuid: blockUuid,
__typename: blockTypeName,
set: {
uuid: setUuid,
__typename: setTypeName,
pagedItems: {
uuid: pagedItemsUuid,
__typename: pagedItemsTypeName,
items: [...items, ...newItems],
hasNext,
excluded,
},
},
},
section,
seo,
apertura,
},
mktg,
social: prev.social,
};
},
});
}, [data, fetchMore]);
I'm trying to edit with the field policy, then eliminating updateQuery() but I get this message (Cache data may be lost when replacing the set field of a Block object.)
Can anyone help me?
const cache = new InMemoryCache({
typePolicies: {
Query: {
fields: {
sezione: {
//keyFields: ["sezione"],
// Don't cache separate results based on
// any of this field's arguments.
keyArgs: false,
// Concatenate the incoming list items with
// the existing list items.
merge(existing, incoming) {
if (!incoming) return existing;
if (!existing) return incoming; // existing will be empty the first time
const { items, ...rest } = incoming;
let result = rest;
result.items = [...existing.items, ...items]; // Merge existing items with the items from incoming
return result;
},
},
},
},
},
});
Add a dataIdFromObject function so that Apollo knows to key against your id field uuid on all objects, since this is different to the default id or _id that apollo looks for.
const cache = new InMemoryCache({
dataIdFromObject(responseObject) {
return `${responseObject.__typename}:${responseObject.uuid}`
},
typePolicies: {
Query: {
fields: {
sezione: {
//keyFields: ["sezione"],
// Don't cache separate results based on
// any of this field's arguments.
keyArgs: false,
// Concatenate the incoming list items with
// the existing list items.
merge(existing, incoming) {
if (!incoming) return existing;
if (!existing) return incoming; // existing will be empty the first time
const { items, ...rest } = incoming;
let result = rest;
result.items = [...existing.items, ...items]; // Merge existing items with the items from incoming
return result;
},
},
},
},
},
});
Note this assumes every object in your GQL schema has a UUID. If there's differences between types you need to do it the other way.
In my management I added the dataIdFromObject() function but that warning keeps coming out.
const dataIdFromObject = (object) => {
// eslint-disable-next-line no-underscore-dangle
const typename = object.__typename;
switch (typename) {
case 'Block':
return `${typename.toLowerCase()}:${object.page}-${object.uuid}`;
case 'ContentSet':
return defaultDataIdFromObject(object);
case 'Image':
return `${typename.toLowerCase()}:${object.src}`;
case 'Page':
return `${typename.toLowerCase()}:${object.slug}`;
case 'PagedContent':
return defaultDataIdFromObject(object);
case 'Leaf':
return defaultDataIdFromObject(object);
default:
if (object.uuid) {
return `${typename.toLowerCase()}:${object.uuid}`;
}
return defaultDataIdFromObject(object); // fall back to default handling
}
// }
};
const cache = new InMemoryCache({
dataIdFromObject,
typePolicies: {
Query: {
fields: {
sezione: {
// Don't cache separate results based on
// any of this field's arguments.
keyArgs: false,
// Concatenate the incoming list items with
// the existing list items.
merge(existing, incoming) {
if (!incoming) return existing;
if (!existing) return incoming; // existing will be empty the first time
const { items, ...rest } = incoming;
let result = rest;
result.items = [...existing.items, ...items]; // Merge existing items with the items from incoming
return result;
},
},
},
},
},
});
I'm trying to add the BlockVariationPicker like in the WordPress Github example:
import { useSelect } from '#wordpress/data';
import {
__experimentalBlockVariationPicker as BlockVariationPicker,
store as blockEditorStore,
} from '#wordpress/block-editor';
const MyBlockVariationPicker = ( { blockName } ) => {
const variations = useSelect(
( select ) => {
const { getBlockVariations } = select( blocksStore );
return getBlockVariations( blockName, 'block' );
},
[ blockName ]
);
return <BlockVariationPicker variations={ variations } />;
};
In my edit function I'm adding:
{ MyBlockVariationPicker }
The block variation picker does not show.
I have already registered my bloc variations with scope block:
registerBlockVariation(
'my/testimonial',
[
{
name: 'testimonial-1',
title: 'Testimonial 1',
scope: ['block'],
attributes: {
example: 'testimonial-1'
},
},
{
name: 'testimonial-2',
title: 'Testimonial 2',
scope: ['block'],
attributes: {
example: 'testimonial-2'
},
}
]
);
The block variations should show in { MyBlockVariationPicker } but the don't. Unfortunately there isn't much documentation about this. How can we render the variations of a block using the Block Variation Picker as shown in the Github example?
Both the Columns and Query block use __experimentalBlockVariationPicker and its a really nice component/UI and I agree, it there aren't many examples of how to use it, most likely as its still 'experimental' and still likely to change.
I found that both the Columns and Query blocks display the BlockVariationPicker by checking if the current block (by clientId) contains any InnerBlocks; if there are none, the BlockVariationPicker is shown. When using this component in your own block, you will need some attribute or property to check whether or not a variation has been selected.
I've put together a basic/working example using the structure of your my/testimonial block + variations and based on how the BlockVariationPicker is implemented in Columns block:
import { get } from 'lodash';
import { useSelect } from '#wordpress/data';
import { registerBlockType, registerBlockVariation, store as blocksStore } from '#wordpress/blocks';
import { useBlockProps, __experimentalBlockVariationPicker as BlockVariationPicker } from '#wordpress/block-editor';
// Create our own BlockVariationPicker
const MyBlockVariationPicker = ({ name, setAttributes }) => { // Note: We need "name" and "setAttributes" from edit() props
const { blockType, variations, defaultVariation } = useSelect(
(select) => {
const { getBlockVariations, getBlockType, getDefaultBlockVariation } = select(blocksStore);
return {
blockType: getBlockType(name),
defaultVariation: getDefaultBlockVariation(name, 'block'),
variations: getBlockVariations(name, 'block')
};
},
[name]
);
return <BlockVariationPicker
variations={variations}
icon={get(blockType, ['icon', 'src'])}
label={get(blockType, ['title'])}
onSelect={(nextVariation = defaultVariation) => {
if (nextVariation.attributes) {
setAttributes(nextVariation.attributes); // Use setAttributes to set the selected variation attributes
}
}}
/>;
};
// Register the Block Variations
registerBlockVariation(
'my/testimonial',
[
{
name: 'testimonial-1',
title: 'Testimonial 1',
icon: 'admin-comments', // Added icon so the variation is visibly different (optional)
scope: ['block'],
attributes: {
example: 'testimonial-1'
},
isDefault: true
},
{
name: 'testimonial-2',
title: 'Testimonial 2',
icon: 'admin-links',
scope: ['block'],
attributes: {
example: 'testimonial-2'
},
}
]
);
registerBlockType('my/testimonial', {
title: 'My Testimonial',
keywords: ['testimonial'],
icon: 'admin-post',
attributes: {
example: {
type: "string", // no default set, example is "undefined"
}
},
edit(props) {
const { attributes, setAttributes } = props;
// If example is undefined, show Variation Picker
if (attributes.example === undefined) {
return (
<MyBlockVariationPicker {...props} />
);
}
// Otherwise show the Editor
return (<div {...useBlockProps()}><h2>{attributes.example}</h2></div>);
},
save: ({ attributes }) => {
return <div {...useBlockProps.save()}><h2>{attributes.example}</h2></div>;
}
})
If you build the above javascript, the resulting block allows you to pick from the two variations on insertion:
Am new in Angular technology and working with Angular with spring boot as back end. Am stuck in reloading data gird.i have a backed API call for populating data gird. My issue was like some time data will change in the response.based on this I need to update my data grid in UI.
Edit 1
Angular.ts file
#ViewChild('modal', { static: false }) modal;
columns = [
{
prop: 'Name',
name: 'name'
},
{
prop: 'Location',
name: 'Location'
},
{
prop: 'Status',
name: 'Status'
}
];
ngOnInit() {
}
getData(name): Observable<Nodes> {
return this.service.getData(name).pipe(map((data) => {
return data;
}));
}
loadInitialData() {
this.getData(this.name).subscribe((data) => {
this.dataFrom = data;
this.service.saveMessage(data);
data.dataNodes.forEach((elm) => {
if (elm.archiveGroups === null) {
return;
}
elm.archiveGroups.forEach(arch => {
if (arch.archives === null) {
return;
}
let row: rowJson;
arch.archives.forEach(arc => {
row = Object.assign(new rowJson(), {
Name: arc.Name,
Location: elm.NodeName,
Status: arc.status,
});
this.rows.push(row)
});
});
});
this.loadingState = false;
this.populateData();
}, err => {
});
}
Edit 2
I have done below changes in ngOnInit method.but status filed not updated
ngOnInit() {
this.updateSubscription = interval(1000).subscribe(
(val) => {
this.getData(this.hostname).subscribe((data) => {
data.dataNodes.forEach((elm) => {
elm.archiveGroups.forEach(arch => {
if (arch.archives === null) {
return;
}
arch.archives.forEach(arc => {
let row: rowJson;
row.Status=arc.status
});
});
});
});
}
);
}
How to update status field based on getData API response.I could see a lot of queries regarding reload. Please guide and suggest a valid Solution
I currently have an axios get request that fetches data from a nasa API and returns it into a list of arrays.
getDataHandler= () => {
axios.get('https://api.nasa.gov/neo/rest/v1/neo/browse?api_key=DEMO_KEY',)
.then((response) => {
const restructuredData = response.data.near_earth_objects.map(
({ name, estimated_diameter, close_approach_data }) => {
const close_approaches = close_approach_data && close_approach_data.length
? close_approach_data.map(({ orbiting_body }) => orbiting_body)
: ["no orbited planet"] // If the array doesn't exist, just use an empty array.
return [
name,
estimated_diameter.kilometers.estimated_diameter_min,
estimated_diameter.kilometers.estimated_diameter_max,
close_approaches[0]
]
})
})
It returns a list of arrays that look like this:
0: (4) ["21277 (1996 TO5)", 1.6016033798, 3.5812940302, "Mars"]
1: (4) ["162038 (1996 DH)", 1.2721987854, 2.844722965, "no orbited planet"]
2: (4) ["189058 (2000 UT16)", 1.332155667, 2.978790628, "Earth"]
3: (4) ["276274 (2002 SS41)", 0.9650614696, 2.1579430484, "Earth"]
4: (4) ["322913 (2002 CM1)", 1.214940408, 2.7166893409, "Jupiter"]
5: (4) ["435730 (2008 UK90)", 0.4411182, 0.9863702813, "no orbited planet"]
Then it gets the list and setState it.
Problem is I have a dropDown menu to only show data from specific planets. So I was wondering if it's possible to map of it again and only keep the ones that are equal to the current selected planet.
And if no planets are selected return all of them.
code i have so far
class MainPage extends Component {
state = {
data: [['name', 'min estimated diameter', 'max estimated diameter', { role: "planet" }]],
dropDownOptions: [
{ value: 'all', label: 'All' },
{ value: 'earth', label: 'Earth' },
{ value: 'mars', label: 'Mars' },
{ value: 'mercury', label: 'Mercury' },
{ value: 'venus', label: 'Venus' },
{ value: 'saturn', label: 'Saturn' },
{ value: 'jupiter', label: 'Jupiter' },
{ value: 'no orbited planet', label: 'No orbited planet'}
],
SelectedDropDownOption: { value: 'all', label: 'All' },
}
componentDidMount() {
this.getDataHandler()
}
getDataHandler= () => {
axios.get('https://api.nasa.gov/neo/rest/v1/neo/browse?api_key=DEMO_KEY',)
.then((response) => {
const restructuredData = response.data.near_earth_objects.map(
({ name, estimated_diameter, close_approach_data }) => {
const close_approaches = close_approach_data &&
close_approach_data.length
? close_approach_data.map(({ orbiting_body }) => orbiting_body)
: ["no orbited planet"]
return [
name,
estimated_diameter.kilometers.estimated_diameter_min,
estimated_diameter.kilometers.estimated_diameter_max,
close_approaches[0]
]
}
)
const joined = this.state.data.concat(restructuredData)
this.setState({ data: joined })
})
.catch(function (error) {
console.log(error);
})
}
DropDownChangeHandler= (SelectedDropDownOption) => {
console.log("hello")
this.setState({SelectedDropDownOption});
}
render () {
console.log(this.state.data)
console.log(this.state.SelectedDropDownOption)
console.log(this.state.SelectedDropDownOption.value)
return (
<React.Fragment>
<DropDown options={this.state.dropDownOptions} onChange={this.getPlanetInformation}/>
<Chart chartData={this.state.data} />
</React.Fragment>
);
}
}
export default MainPage;
You can use filter method to achieve your goal. You loop over every sub array and you keep only those which includes the require planet name passed as function parameter.
const arrayList = [["21277 (1996 TO5)", 1.6016033798, 3.5812940302, "Mars"], ["162038 (1996 DH)", 1.2721987854, 2.844722965, "no orbited planet"], ["189058 (2000 UT16)", 1.332155667, 2.978790628, "Earth"],["276274 (2002 SS41)", 0.9650614696, 2.1579430484, "Earth"], ["322913 (2002 CM1)", 1.214940408, 2.7166893409, "Jupiter"]]
const getPlanetInformation = (planet) => {
const information = arrayList.filter(item => item.includes(planet))
console.log(information)
return information.length ? information : arrayList
}
If there is no planet selected from your dropdown value or the selected doesn't exists inside your array, you can just return the initial value.
After some debugging, I found out that when the page loads, #skip is doing what I want which is blocking the execution of the query on page loading. However, when the submit button is clicked the app crashes.
I do not understand why the start and end are undefined?
variables: {start: undefined, end: undefined, skipFi: true}
If I remove skipF: true from following the app works fine:
export default graphql(getObjQ, {
options: (props) => ({
variables: {
start: props.start,
end: props.end,
skipF: true
}
})
)(Comp);
I am trying to apply the concept from here to my app:
export default graphql(gql`
query SearchQuery($query: String, $first: Int, $skip: Boolean!) {
search(query: $query, first: $first) #skip(if: $skip) {
edges {
....
}
}
}
`, { options: {variables: { skip: true } }})(Input);
The handleSubmit function looks like this:
handleSubmit = event => {
event.preventDefault();
this.setState({
errMsg: "",
start: new Date(document.getElementById("start").value).valueOf(),
end: new Date(document.getElementById("end").value).valueOf(),
submit: true,
}, () => {
this.props.data.refetch({
start: this.state.start,
end:this.state.end,
});
The query looks like this which is in a separate file/component:
const Query =gql`
query getObjQ($start: Float!, $end: Float!, $skipF: Boolean!
)
{
abs(start: $start, end:$end) #skip(if: $skipF)
Too many 'moving parts' - try hardcoded values first:
handleSubmit = event => {
event.preventDefault();
this.props.data.refetch({
start: XXXXXXXXXXX,
end: YYYYYYYYY,
skipF: false
});
}
UPDATE:
method for debugging options parameters (return object):
export default graphql(getObjQ, {
options: (props) => {
console.log(props.start);
return {
variables: {
start: props.start,
end: props.end,
skipF: true
}
}
}
})(Comp);