Is there an existing library that would do this?
I want to be able to have code on the client side where the user chooses something, it makes a call to the server, and the server sends back "for this option, you need a have a text field called foo and a select field called bar with the following options, this one is selected, etc", and then the client side builds the next part of the form from that information. Or if they choose a different option, a different set of fields and values is returned from the server and populated on the screen. Also it might cascade so after the first selection we need a select field with some options, and then depending what they select on that select field the next field might be another select field or it might be a text input field.
Has anybody done anything like that? Is my best choice to have the AJAX call return some html that I just stuff into a div, or can I do it field by field and value by value?
If it matters, the back end is going to be written in Perl/MASON, and the front end will be using Javascript/JQuery/JQuery-UI.
I would use jquery and submit AJAX calls to whatever backend system you choose. Have this backend system compute the necessary changes and return the info as JSON. Let JQuery parse it for you and append the necessary form elements. However, it seems like under alot of use cases these decisions could be made on the client side without even talking to the server just as we pre validate form input before allowing posting to the server. I don't, however, have your requirements in front of me so I am sure there is a reason you want to get the info back from the server.
P.S. please do not return pure html from the back end to the client....ever.
Related
I am developing a series of Slack apps for my workspace, and some of them are meant to interact with the content (messages) delivered by the other apps : extracting content IDs that may be referred to by other messages
A concrete example :
Suppose I have an app A "FindUser" that is capable of giving me the user profile when a slack user types find me#example.com, and it replies in the thread with a formatted view of the user profile
I am developing an app B "EditTags", which basically gives me a right click option with "edit tags" (see Slack's Interactive Components/Actions), the idea being that a user could first ask app A to find a user, and then right click on the reply from App A and click the "edit tags" action given by the other app. What this app B does it actually retrieve the tags for the user mentionned by the previous message from app A, and in another reply to the thread it gives some controls to either delete an existing tag OR it shows a select with autocomplete to add new tags.
The B app needs to retrieve the user ID that the A app mentionned previously. So I need some way to pass that data directly in the slack message. When looking at the examples, slack does not seem to provide a way to add arbitrary "metadata" to a message, am I wrong ? Do you have workaround for this ? I mean I could totally send the user ID say, in the footer, so I can just read the footer, but I was planning to use the footer for something else... Is there a way to pass metadata hrough properties that would be hidden to the end user ?
Although this does not feel relevant, I am building a slack nodeJS app using the node slack sdk (and especially the #slack/interactive-messages package)
For the most part the Slack API does not provide any official means to attach custom data / meta data to messages. But with some simple "hacks" it is still possible. Here is how:
Approach
The basic approach is to use an existing field of the message as container for your data. Obviously you want to pick a field that is not directly linked to Slack functionality.
Some field are not always needed, so you can just use that field as data container. Or if its needed, you can include the functional value of that field along with your custom data in the data container.
For example for message buttons you could use the value field of a button and structure your code in a way that you do not need it in its original function. Usually its sufficient to know which button the user client (via the name field), so the value field is free to be used for your custom data. Or you can include the functional value of your button along with the custom data in a data container (e.g. a JSON string) in that field.
Serialization
All messages are transported through HTTP and mostly encoded as UTF-8 in JSON. So you want to serialize / de-serialize your data accordingly, especially if its binary data. If possible I would recommend to use JSON.
Length
The maximum allowed length of most fields is documented in the official Slack API documentation. e.g. for the value field for message buttons can contain up to 2.000 characters. Keep in mind that you need to consider the length of your data after serialization. e.g. if you convert binary data into Base64 so it can be transported with HTTP you will end up with about 1.33 characters for every byte.
Contents
In general I would recommend to keep your data container as small as possible and not include the actual data, but only IDs. Here are two common approaches:
Include IDs of your data objects and load the actual objects
from a data store when the request is later processed.
Include the ID of server session and when processing the request you
can restore the corresponding server session which contains all data
objects.
In addition you might need to include functional values so that the functionality of the field you are using still works (e.g. value of a menu option, see below)
Implementation
Dialogs
Dialogs provide an official field for custom data called state. Up to 3.000 characters.
Message buttons
For Message buttons you can use the message action fields / value. Up to 2.000 characters. Its also possible to use the name field, but I would advise against it, because the maximum allowed length of that field is not documented.
Message menus
For Message menus you can use the value field of an option or the name field of the menu action.
Usually the value field is the better approach, since you have a documented max length of 2.000 and it gives you more flexibility. However, you will need to combine you custom data with the actual functional value for each option. Also, this will not work for dynamic select elements (like users), where you can not control the value field.
When using the name field note, keep in mind that the maximum allowed length of name is not documented, so you want to keep you data as short as possible. Also, if you want to use more than one menu per attachment you need to include the actual name of the menu into your data container.
Normal message attachments
Normal message attachments do not contain any suitable field to be used as container for custom data, since all fields are linked to Slack functionality.
Technically you could use the fallback field, but only if you are 100% sure that your app is never used on a client that can not display attachments. Otherwise your data will be displayed to the user.
I have read a lot of answers relating to how to dynamically add forms to an model formset in Django and can successfully implement that. However, I would now like to submit the formset with AJAX. This is mostly working now but I have an issue that I can't find a solution to in any other answer:
If you dynamically add a form to the formset, you give it a new form id number that is one larger than the maximum the form currently has and you also increment the management TOTAL_FORMS count by one. The newly added form then saves successfully as a new object.
I am trying to submit by AJAX so the user can continue editing without having the page refresh. The formset saves fine but any dynamically added forms are now existing objects. To account for this I need to increment the INITIAL_FORMS count on the management form when the save is successful. Easy enough. However, I've also realised I need to give the newly created objects an ID since they now exist in the database.
How can I get my view to tell me the ID of the new objects in its response to the AJAX call? Or is there a better way of looking at this?
Django forms and formsets are intended for classic browser-based posting of data. Though they can definitely be made to work with Javascript, the more you want to part from the normal behavior, the more complex it gets.
Depending on your requirements, you might start thinking about dropping it and switch to Javascript + REST endpoint. Of course, if you need progressive enhancements and you are required to have it work without javascript, that's not an option.
In any case, you want to have a customized view for posting from JS, so that you can get the result back and parse it easily in your AJAX handler. Probably some JSON.
There are several approaches you could take.
Have your AJAX send data to a different URL. This is pertinent if you have an API or are planning to build one at some point. So your form, when submitted normally, will do its old-style processing but your AJAX will talk to the API endpoint instead.
For instance, your form send to https://example.com/myform, but your Javascript code talks to REST api at https://example.com/api/v1/mymodel/ (sending PUT, POST and DELETE requests as appropriate).
Or if you don't have an API and building one seems overkill, you may just alter your view so it formats its output differently depending on whether the data is being submitted in the regular way or using AJAX.
You'd go about it like this:
class MyFormView(.....):
def render_to_response(self, context, **kwargs):
if self.request.is_ajax():
return self.render_to_json(context, **kwargs)
return super().render_to_response(context, **kwargs)
def render_to_json(context, **kwargs):
data = {
# see below!
}
return HttpResponse(
content=json.dumps(data).encode('ascii'),
content_type='application/json',
)
This is just an outline. You need to ensure is_ajax will detect it properly (see django doc). And you need to properly build data from context: extract the things you want to send back to your JS code and put them in the dict.
You will find it's manageable if you just do this for one, maybe two views in your project, but very quickly you'll want to have a small API instead, especially given how easy it is to build one with packages such as Django REST framework.
In your view, where you save the object, AFTER the save, the object.id will contain the new id for the object, which you can return via json or however you want in your ajax response, and then yes you will need to fill that into the formset row so that it will be submitted the next time.
One thing you have to watch out for is that django expects all existing rows to be at the top of the formset, and any new rows to be at the bottom. Otherwise, the formset save will complain about missing id's. So if you're doing any kind of sorting in your javascript, you can't do that.. unless you do quite a bit of fixing of all the field names etc in the formset. The formset code uses the numbers in the management form to determine which rows to insert and which rows to update, it does not do it on the basis of whether or not an id is present. Unfortunately...
Im looking for a way to add a new row and keep the form data together with the Save button enabled, to have the chance to resend the same data already sent.
What im trying to achieve is to facilitate the submission of similar-but-not-equal rows. So, for example, if a merchant receives an order all of the same X product, but with slightly differences, he can keep the common fields after saving a product and only change the different properties to submit the next one, and so on.
Then the server will throw an error if exactly the same data is sent more than once.
As per our discussion I would refer to the following as an example of adding a custom button to the Add form:
How to add custom buttons to JqGrid add/edit forms?
as for saving the information you can use the the documentation as an example, I think the beforeSubmit event would work for saving the field data
In jqGrid 4.4.4, file jquery.jqGrid.min.js:
At line 279, after 'beforeSubmit' takes place, you will find the following statement: if(k[0]&&!b[d.p.id].processing), the second part of the test means something like 'if request is not being processed', then after the 'processing' variable is set to true, the request to the server is performed.
What prevents to resend data is that the processing variable is never set back to false 'afterSubmit' for example.
So, my solution was to do exactly that: b[d.p.id].processing=false; at the end of the if block performing the action, this is done on line 287, col 55.
This way i can resend slightly different 'products' and just let the server to manage errors.
I suppose it could be a bug in the library to not 'close' the processing state by setting back the variable to false.
In order to use some AJAX calls, we use often some input type="hidden". But these values can be easily changed. So, is it a builtin rails feature than permit to send date to AJAX, withouth being usable by user, or than can't be changed by user ?
In my current rails apps, i'm using filters for discard all malicious actions on my controllers. I am not building a public API, so i don't really need more powerful checks.
But for examples, i have an apotomo widget displaying some data, using some input hidden. But if you change it, you can access to another data set. In my case, it's not really an issue, cause all these users have the right to access these data sets anyway.
But is it some manner to give datas to ajax call, in a secure way ? Or the only security, is about rights management ?
All input that comes from the user is insecure as you do not have control over it! Users even do not need a webbrowser but can use some other program (like curl or wget) to send manipulated data.
As you state, using a whitelist (not a blacklist as you can never be sure of all bad, but of all good!) is a good way to start.
To make sure the hidden fields have not been changed you can use some kind of checksum that is calculated on server side using a fixed secret. This secret must never be exposed to your visitors!
hash = md5(field_1 + field_2 + field_3 + my_secret)
When these four hidden fields (field_1..3, hash) arrive in your form you can recalculate the hash and compare it with the params[:hash] in order to be sure the field_1 to field_3 have not been changed.
I've been having a look at several MVC frameworks (like rails, merb, cakephp, codeignitier, and similars...)
All the samples I've seen are basically plain and simple CRUD pages, carrying all the infr needed in the querystring and the posted field values.
I've got a couple of apps made with some sort of framework built with classic asp.
This framework handles some CRUD stuff a little more complex than the examples I found.
Something like master-detail, filtering by example, paging, sorting and similars.
I have a controller class that it's just a finite state machine, that goes thru diferent states (like new, browse, filter, show, etc.), then performs the appropiate action depending on the event raised and finally retrieves the neede info to the calling page.
To achieve this I have several hidden inputs to keep the state of the web page (like current id, filter criterias, order criterias, previous state, previous event, well, you get the idea)
What do you think would be the finnest approach to achieve this kind of funcionality?
hidden inputs built in the view and used from the controller??? (I guess that would be the equivalent of what I'm doing right now in classi asp)
--
(added in response to tvanfosson)
basically, my question refers to the third category, the context-dependent setting (in respect to the other two categories I agree with you) the info I was storing in hidden fields to store them on the querystring, I guess that when you click on the "next page" you include everything you need to save in the querystring, right? so that piece of query string gets appended in each and every link that performns some kind of action...
I'm not sure, what are the advantages and disadvantages of using the querystring instead of hidden inputs???
I use different strategies depending on the character of the actual data. Things that are preferences, like default page size, I keep in a Preferences object (table) that is associated with the current logged in user and retrieve from there when needed.
Persistent settings associated with the current logon, like filter settings for a page, are stored in the user's session. Generally these are things that if a user sets them in the current session they should remain sticky. I think filter settings and visibility are like this. If I filter a list, navigate away from it to drill down into a particular item, then come back to the list, I want my filter settings to be reapplied -- so I make it part of the session.
Context-dependent settings -- like the current sort column or page number, are controlled using query parameters. Paging and sort controls (links) are built with the appropriate query parameters to "do the right thing" when clicked and pass any necessary query parameters to maintain or update the current context of the control. Using the query parameters allows you to use an HTTP GET, which is bookmarkable, rather than a POST. Using hidden form parameters makes it much harder for the user to save or enter a URL that takes them directly where they want to go. This is probably more useful for sorting than it is for paging, but the principle applies equally.