# EditLinkPage, AddLinkPage, and DeleteLinkPage

## Overview

EditLinkPage, AddLinkPage, and DeleteLinkPage are all very similar in their design. We'll be examining EditLinkPage closely, and I'll mention any differences between it and the others at the end.

### Forms Processing

Here's where we get to see how the forms processing is done (or at least one method that works). When this page is requested, a child resource is given that doesn't correspond to a page. Instead, it is an integer that corresponds to a bookmark's id, and that is how we know what bookmark the user wishes to edit.

One difference in this page is that I chose to do the layout of the components in the template, instead of generating the majority of the HTML using lmx (just to show how it's done). I'm lead to understand that in a production environment, this is more likely to be the way it's done (but either way is still correct).

The page itself is straightforward, one combo box for the user to select the category they wish to add the bookmark under, a Name and a URL textbox, a submit button that causes the edit to be committed, and a cancel link (because I couldn't quite figure out how to make it a button :-/) that brings the user back to the EditLink page.

## Details

### getDynamicChild()

As in the previous example, we set up a form that posts to the originating page This allows us to handle form validation and redirection from getDynamicChild() (not that there's much validation here, but if you wanted to...).

getDynamicChild has the signature getDynamicChild(self, name, request). The name argument is the path of the child page in the request (AFAICT). Here, I've renamed it to bmark_id, as that is what we are using this path to represent, the id of the bookmark we wish to edit. So we call the storage object and tell it to give us all the bookmark objects with id=bmark_id (which should be only one object), we set this to an instance attribute to save for later, and then return this instance of EditLinkPage.

When the user clicks the submit button, it posts back to itself (it's originating page), and getDynamicChild is called (again). This time, however, because we have placed an invisible submit element in the form, we know that if this key is present in request.args, that this is not the first time that we're going through this, and now we have to store the data. Because each key in request.args is a list, and we know there's only going to be one value in each list, we can safely take [0] for each of our attributes, tell the storage object to update it and return the user to the EditPage.

### The wvupdates and wmfactories

First, we get the combo box data from our storage object. This is simply a list of category names culled from the data source. We create a list of Option objects, and we set the bookmark's category as the default selected combobox selection item. Here I use a convenience method add_opts to render the Option list on a node.

Since the two textboxes are basically the same, I chose to mark the tags with model=linkname and model=url and let the appropriate wmfactory return the correct name attribute to the view. I did this because the view of these two elements is the same (a textbox) and their only differences are the default value they're filled in with and the value they'll represent upon submittal. This is to show that the same view can be used with different models to achieve different results, and save typing.

## AddLinkPage

The AddLinkPage is almost identical to the EditLinkPage, the only difference being that there are no default values inserted, and a different method is called on the storage object. It uses the exact same strategy to handle the form.

## DeleteLinkPage

The DeleteLinkPage is even simpler still, as it doesn't have a view. All this page does is call the storage object's delete_Bookmark method with the argument passed to it as the name parameter.

next | prev | toc