I have an older project in Ionic v1 (Angular 1.x) where users can create groups and add members. I need to add a capability to the App for the group Admin to ask questions to group members - sort of a dynamic form. The questions can be of three types - a Yes/No (to be shown as a toggle), String (input Text) and a question with choices (to be shown as a select drop down). The number of questions can vary.
The questions are stored along the lines of the hash below.
{
id1: {q: "question1", type: "String"},
id2: {q: "question2", type: "Yes/No"}
id3: {q: "question3", type: "Choice", choices: "Choice1, Choice2, Choice3"},
id4: {q: "question4", type: "String"},
id5: {q: "question5", type: "Yes/No"}
id6: {q: "question6", type: "Choice", choices: "Choice4, Choice5, Choice6"}
}
I am trying to think of the best way to be able to show these questions dynamically to the user and collect the answers but not quite sure what's the best way to do this. I started looking at trying to create a Directive but wanted to get advice before spending too much time down a path.
Look forward to your thoughts and suggestions.
-S
I would suggest a simpler approach than using a directive, unless you have the need to reuse this as a component across multiple views. Start by having ng-repeat="(key, value) in questions" where questions is the name of your object. Then simply show/hide different forms for each question based on value.type: ng-if="value.type=='String'"...
The form you show in each case would be a checkbox for yes/no, textarea or input(type=text) for string and radio buttons for choice.
I'm not providing full code as I assume you know enough Angular to be able to create those - if not each case is an easy google away. One further thing you'll need is a place on each question for the model (i.e., the user's answer), which might be value.answer. For example:
<input type="checkbox" ng-model="value.answer">
Does this make sense?
Related
Creating an eCommerce type react application and part of it is merchants can create product listings(item title, item description, item price, etc). How do I allow them to add options to the listing like Size, Color, etc. It seems more confusing than just having input fields that can change a state variable.
An example of what a completed array should look like after a user enters options:
const options = [
{
optionName: 'Size',
values: ['small', 'medium', 'large']
},
{
optionName: 'Color',
values: ['blue', 'black', 'white', 'tan'],
}
]
Above is how it should be constructed to be sent to server.
Let me know if any more clarification is needed.
What you're describing is dynamic form construction, and is always much more complicated than a static form. This is not an easy feature to implement.
What you've sketched out there as dummy API request data is essentially the solution -- you just need to provide UI that enables that solution. Presumably you have an object that holds all your form data, so you can add a field like userDefinedOptions that gets initialized with an empty array.
Then, you'll need UI elements to allow adding a new user-defined option, which will probably include the display name of the option, as well as the list of choices for that option. This UI would then call an event handler that inserts the inputted values into your list of user-defined options.
Dynamic forms can get very messy very fast, so I'd recommend looking into a form library to handle some of the overhead. You'll also need to validate the dynamic user data before sending it off to the API.
Hope that helps!
I'm writing an sort of project management app that'll have a large number of "tasks" with a lot of properties within them that'll be rendered throughout the app. I am looking at using React Query to prefetch, cache locally, and update this data from the server.
One key architectural thing I want to get right is that when I query or mutate Tasks[123] that I affect a single underlying object in the state and not get stuck with duplicate data everywhere. On first glance React Query seems to be perfect for this job if the Query Keys are setup right. However in their examples they don't seem to do this (or I'm failing to understand).
In their Basic Example they fetch some Posts on start and query using queryClient.getQueryData(["post", post.id]). As far as I can tell this is causing the data to be duplicated if I look at the provided ReactQueryDevtools window in the example.
Am I correct in thinking the example should be rewritten to use something like queryClient.getQueryData(["posts", {id: post.id} ])?
That is indeed the way I am setting up my query keys, so that I can do: queryClient.invalidateQueries(['posts']) and it invalidates all of them. But sometimes, you need more fine granular control. If that's the case, I'd do:
["posts", "list", { filter: "all" }]
["posts", "list", { filter: "published" }]
["posts", "detail", 1]
["posts", "detail", 2]
that way, I can still tackle everything with ["posts"], all lists with ["posts", "list"], all details with ["posts", "detail"] and a specific detail with ["posts", "detail", id] etc.
It is also good practice to have a queryKeyFactory to create those keys, something like:
const postKeys = {
prefix: "posts",
lists: [postKeys.prefix, "list"],
list: (filter) => [...postKeys.lists, { filter }],
details: [postKeys.prefix, "detail"],
detail: (id) => [...postKeys.details, id]
}
Of course, I'm talking about "at scale" here. None of this is really needed for a todo app :)
I just started using Cloud Firestore for the CMS side of a web app hosted with the firebase platform. I know this is a very new product, but I have done my due diligence, reviewing all the docs: https://cloud.google.com/firestore/docs/, and SO forums: https://stackoverflow.com/questions/tagged/google-cloud-firestore- I can't find an answer, so I was hoping for some simple guidance.
I was wondering if there was a way to just query certain values of an object by key name, stored in an array. I would be using this for an selector element, For example- I have a very long list of stories as an array:
DATA
[ {title: "Title One", id: uid1, content: "very long string.."}, {title: "Title Two", id: uid2, content: "very long string.."} ...]
ELEMENT
<select onchange=fetchStoryByUID(story.val)>
<option value=story.uid>story.title</option>
</select>
I'd like to get just the story titles and uids to append to this element, without having to return all of the object keys and values. The response would be something like:
EXAMPLE QUERY RESPONSE (list of only titles and uids)
[{title: "Title One", id: uid2}, {title: "Title Two", id: uid2} ...]
Perhaps I need to re-think my data schema or something, but I feel that this is a common scenario that I didn't see covered in the docs. Any help would be greatly appreciated!! Thanks
Right now there is no way to retrieve partial documents using any of the Cloud Firestore mobile SDKs (Android, iOS, or JavaScript). Some of our server-side SDKs offer a select() method which allows you to do this. It does not affect pricing but it will save bandwidth.
In general you should store data in a document that you intend to fetch all at once. In your example it may make sense to store the content as another document and only fetch it when needed.
If you are using an SQL database, it's very straightforward to develop a user interface for CRUD operations. Since the schema is defined, it's obvious how many inputs you need in a form, etc.
But when using a schema-less NoSQL approach for storage, how do you build interfaces since you don't know exactly what to expect from the types of data being stored? For example if you had a database of cars:
var cars = [
{ model: "BMW", color: "Red", manufactured: 2016 },
{ model: "Mercedes", type: "Coupe", color: "Black", manufactured: “1-1-2017” }
];
If you needed to create a user interface so you could access and edit this data, you have no clue how many inputs you need since there is no schema. How do UI developers solve this problem?
Do you have a bunch of if statements to test if every possible attribute exists in the record before showing the proper inputs?
// psuedo code
if ($car.hasKey("model") ) {
// Show the "Model" input form element
}
if ($car.hasKey("type") ) {
// Show the "Type" input form element
}
if ($car.hasKey("color") ) {
// Show the "Color" input form element
}
if ($car.hasKey("manufactured") ) {
// Show the "Manufactured" input form element
}
If you needed to create a user interface so you could access and edit this data, you have no clue how many inputs you need since there is no schema. How do UI developers solve this problem?
You solve this by reasoning from feature requirements. Emphatically, you do not try to generate forms (automatically or otherwise) from schemas: that is a recipe for poor UX even if you do have a comprehensive, canonical and unequivocal schema to hand.
Instead: you know what your 'use cases' are (you ask users) and then you build exactly those.
So the question becomes:
What do you do when your data item/instance does not contain a particular object/field/key which you did expect?
What do you do when your instance contains fields which you do not know what to do with?
The answer for #1 is pretty straightforward, and basically just the same as dealing with schema changes: assume/present sane defaults or handle null values gracefully. That is: permit your users to add such fields later where they make sense and do not choke on objects that lack them.
The answer for #2 is more complicated and it is going to depend heavily on the application and its environment (for example: is it the sole consumer of the data, or are there other consumers to consider as well). One option could be normalisation: you prune such extraneous fields on saving, so objects become normalised over time as they are updated by the users. An alternative could be preservation: you keep any fields you do not know as-is, and you take pains to preserve them through every layer of your application.
Let me explain my situation:
I have model with array field inside it
Ext.define('MyModel',{
extend: 'Ext.data.Model',
fields: [
{ name: 'myfield', type: 'array' }
]
})
that contents data like this
data = Ext.create('MyModel',{
myfield: [ 'one', 'two', 'three', 'four' ]
})
I want to extend Ext.form.field.Base to create field that treats this array as todo-list and contains items inside itself ( Ext.form.field.Trigger to add "todo" and Ext.ListView to display "todo's" ).
I don't know how difficult it is to make Ext.form.field.Base contain items and are there any better possible solutions.
Field must get array on loadRecord() and give it on getRecord() of Form.
Other possible solutions I see:
1) Make Field only with html-template and vanilla-javascript ( bad because why to implement things that are already present in ExtJS )
2) Model relations ( bad because I have to implement 'create, update and delete' for each related model and load them manually )
Thank you for reading, any ideas are welcome!
Not related directly to your question, but "array" is not a valid field type for a Ext.data.Field. Use 'auto' for no data conversion, or just don't assign a type.
Re: the custom, complex form field, it's certainly possible with ExtJS, and creating an extension of the Trigger field is definitely what you'll want to do. Here's an example of a custom trigger field that handles complex data: http://existdissolve.com/2012/12/extjs-4-custom-editor-for-property-grid/. The example is for a custom property grid, but the principle is the same for any custom form field.
The most important parts in your custom field are going to be the implementation of the createPicker() method and whatever mechanism you define for setting the value of the underlying field.
Hope this gives you a good place to start.