Summary: Create a list where entries can easily be inserted and deleted
Version: 1.10
Status: unmaintained and not without bugs (use AddDeleteLine2)
Maintainer: Nils Knappmeier (
Discussion: AddDeleteLine-Talk

As of version 1.5, the name of textfields is not prepended with a 'text' anymore. If you use fields from the Forms directives, you have to use the original field name in the (:appendas...:) directive

There is now a version 2.0 beta available, it is describe here: AddDeleteLine2


How can I create something like a list where people can easily insert and delete entries without having to click on edit?


Copy the file adddeleteline.phpΔ into your cookbook directory and insert


into your local/config.php.


Originally, AddDeleteLine was designed to insert single lines somewhere in the page and remove them again, if needed. (That's what the name suggests, isn't it. In the course of development a number of features were included. The following paragraphs start with the basic features and then advance to the more complicated ones.

Adding a single line

(:form party:)
||Name                    ||(:input text name:)   ||
||I am bringing something: ||(:input text brings:) ||
|| (:submit Enter:) ||||
(:appendas "||{name} ||{brings}  || (:delete:)":)

||!Name ||!Brings ||
(:addhere party:)

The result is an HTML form, where all (:textfield xxx:) are input fields. The (:appendas ...:) line specifies what the new line will look like. The (:addhere ... :) line specifies where the line will be inserted. You could alternatively use (:prependhere ... :) for this. In the example, a (:delete:) statement will always be inserted in the new line. It converts to a link that deletes the current line.

Inserting the current date and time

The following special markup can be used in (:appendas...:):

Inserts the current date using the PHP function 'date'. fmt is a format string as specified in (since AddDeleteLine version 1.5)
Inserts the current date using the PHP function 'strftime'. fmt is a format string as specified in (since AddDeleteLine version 1.9)

Both PHP functions offer different features which might both be useful: As far as I can see, 'strftime' does not provide month- and day-numbers without the leading zero (1..31 instead of 01..31) which 'date' does. However 'strftime' provides localized string for the names of weekdays and months, which 'date' does not.

Adding data to a different page

If you want your form's output to add lines to a page other than the one where the input form is, you can use the following markup

(:form name target=TargetPage:)

where TargetPage can be either AnyGroup.AnyPage (to link to a different group or AnyPage (to link to a page in the same group).

When adding a line to a different page, you must put the (:addhere ... :) or (:prependhere ... :) directive onto the target page to specify where the text should be added.

Adding multiple lines

Place the form on Any_Group.Input_Page.

The form's second line specifies the output page

(:form party2 target=Some_Group.Output_Page:)
||Name:     ||(:input text name:)   ||
||Bringing: ||(:input text brings:) ||
||Eyes:  ||(:input radio eyes one:) one  ||
||       ||(:input radio eyes two:) two  ||
||My ideas for where to have it: ||(:input textarea textwhere rows=5 cols=50:) ||
|| (:submit Enter:) ||||

(:comment : line breaks in the following would be removed in actual use:)

(:appendas "(:table width=98% border=1 align=center cellspacing=0:) \n
(:cellnr width=20%:)Name: \n(:cell:) '''{name}''' \n
(:cellnr:)Bringing: \n(:cell:) {brings} \n
(:cellnr:)Eyes: \n(:cell:){eyes} \n
(:cellnr:)Location: \n(:cell:){where} \n(:tableend:) \n":)

(:comment : ends section w/extra linebreaks - all of the above should be on a single line:)


(:comment : here you are optionally including the output\\
(from line 3 down of the output page) below the form, back\\
on the input page:)
(:include Some_Group.Output_Page lines=3..:) 

Now, on the target, Some_Group.Output_Page, you have the directives:

(:redirect Any_Group.Input_Page:)
(:prependhere party2:)

Entering an Author and a Change Summary

If you also want to enter an author and a page summary for the page history, add the following fields to your form declaration:

||Author: ||(:input text author:)  ||
||Summary: ||(:input text csum:)   ||


  • Be aware that, some field-names may have meanings beyond the scope of this recipe (for example 'n', 'csum', 'author'). If you use these field-names in the form, you may experience unwanted side-effects. But, on the other hand, this allows a great flexibility, such as inserting the author-name in the page by using {author} in the (:appendas...:)-directive.
  • If you are going to have multiple lines of output, don't bother having the delete link in the output, because it won't work to remove an entire entry. There might be a way around this, but it is not simply done and probably includes some markup. If there is interest in this, I could do this some time. Just contact the author.
    • I'd like this -- Tegan
  • The user must have read and edit rights to the output page. Depending on the situation, this may be reason to have the output page separate from (although optionally "included" on) the input page - so that while the users have edit rights, they do not necessarily access the page (so are unlikely to attempt to edit it). This is mere security through obscurity. same thing here. I guess this could be done. Contact the author if you need this.
    • What could be done? Configure so that users can use the form without having edit rights to the target page? I'd like that -- Tegan
  • The way the script runs, it posts the new content to the output page, and then takes the user to that page. If you don't want the user to arrive at the output page (see the previous note for one reason), you can use the redirection shown in the example. If you put a redirection directive at the top of the output page, you'll probably want to suppress the "redirected from..." notice for the or wikigroup of the page to which the redirect sends the user (which in the example is the form input page). Remember, that if you want to collect private data on a hidden page, you should not do it this way. It is easy to look at the output page manually. If you want people to enter data, but no one except you should be able to read it, there have to be made some modifications to the script.
  • You can create a per-group customization to address the issues raised in the last two notes: create a local/Some_Group.php file, containing:
<?php if (!defined('PmWiki')) exit();

	// Require author name -
		$EnablePostAuthorRequired = 0;

	// Suppress display of redirection notice
		$PageRedirectFmt = '';

Even with this customization, anyone can look at the target page with the proper URL.

Technical requirements

  • This recipe was last tested on PmWiki version: 2.1.24
  • This recipe requires at least PmWiki version: 2.0.0
  • This recipe, version 1.0 was installed here the Sep 25, 2005


Bugfix: "<", "&", ">" may now be used in (:appendas...:)
Adding {strftime:fmt} as alternative to {date:fmt}
Fixing the bug of 1.6 and 1.7 more elegantly.
Bugfix: Like 1.6 only for the (:delete:) functionality.
Bugfix: Target URL of the AddDeleteLine-Form changed to point to pmwiki.php, even when using CleanUrls. This prevents data loss caused by the rewrite-Engine.
Feature: {data:...} markup in the (:appendas...:)-string allows to insert the current date into data
Bugfix: Entered quotes ( " and ' ) are not accidently prepended with a backslash anymore. Furthermore, the (:form ...:)-directive was extended to support the format (:form name target=TargetPage:) which allows posting lines to different wiki-pages without the ugly workaround of manually inserting a hidden input field.
Bugfix: "\n" is not accidently converted to "n" anymore. (Thanks to Tegan Dowling for finding this bug) Additionally, when deleting a line, an integrity check is done. Since the script counts the (:delete:)-directives, when looking for the right line to delete, it might happen that it gets the wrong line, if the page has been edited between "view" and "deleteline". Now, there an additional md5-checksum checked. If it does not match, the user is requested to "Try again!"
In the (:appendas ...:) directive "\n" can be used to create a newline. Note that (:delete ... :) on deletes a single line, so if you use it with "\n" in a (:appendas:) not the whole record will be deleted.
Changed (:input...:) directive to (:textfield...:) in order to avoid conflicts with Forms
First version

See Also

Temporary sample page, until Pm sets something up on


Nils Knappmeier Tegan Dowling


See discussion at AddDeleteLine-Talk

Category: Forms

User notes? : If you use, used or reviewed this recipe, you can add your name. These statistics appear in the Cookbook listings and will help newcomers browsing through the wiki.