We launched new forums in March 2019—join us there. In a hurry for help with your website? Get Help Now!
    • 26289
    • 6 Posts
    Hello all,

    I currently have a site with a section that allows employers to submit job listings. I currently use a classifieds ad manager, but I am not very happy with it. I would like to know the easiest way to use MODx and related add-ons to do the same thing. I don’t want to re-invent the wheel or do a lot of programming because I think MODx is quite powerful already. Basically I need users to be able to submit data into a form. Some of the form elements will be text fields, others drowdown lists for pre-defined values, others will be radio buttons. Then, I need users to be able to browse the submissions in a tabular or list format, preferably with the ability to search and sort based on different fields. The entries should be clickable to view a full page listing for any entry. The users who submit the listings need to be able to delete and modify them. I’ve found...

    http://www.modxcms.com/MakeForm-619.html
    http://modxcms.com/MakeTable-622.html

    ...which look promising, but I’m not sure about the full page listing or being able to delete the entries. I just would like to know if MODx is the right path here before I invest much time in it.

    Thanks a lot for your help!
      • 22303 MODX Staff
      • 10,725 Posts
      Hi sb73542,

      As the author, I use those classes in a lot of the forms I build, in a variety of ways, on my client projects.

      I usually do something similar to the code fragment below for processing forms; this should reveal how to easily delete items, with a delete confirmation step/form (please note this is not complete functional snippet code, just some fragments showing some possibilities):
      <?php
      
      //INITIALIZE AND LOAD DATA AND THE MAKEFORM CLASS HERE
      // (left out for brevity)
      
      // set some required fields
      $requiredFields= array (
          'Username' => 'web_users:user_name',
          'Password' => 'web_users:password',
          'Email address' => 'web_user_attributes:email',
          'First name' => 'person:first_name',
          'Last name' => 'person:last_name',
          'Expiration date' => 'member:expire_date',
          'Street address' => 'address:street',
          'City' => 'address:city',
          'State' => 'address:state',
          'Zip' => 'address:zip',
      );
      $invalidFields= array ();
      $deleteConfirm= false;
      if (isset ($_POST)) {
          if (isset ($_POST['save']) || isset ($_POST['save_x'])) {
              foreach ($_POST as $post_key => $post_val) {
                  if (empty ($post_val) && $key= array_search($post_key, $requiredFields, true)) {
                      $invalidFields[$post_key]= $key;
                  }
              }
      
              if (empty ($invalidFields)) {
                  // DO YOUR INSERTS/UPDATES/ETC. HERE
                  //  (left out for brevity)
              } else {
                  $modx->setPlaceholder('messagebox', '<p class="warning">' . implode('<br />', $invalidFields) . '</p>');
              }
          }
          elseif (isset ($_POST['delete_confirm']) || isset ($_POST['delete_confirm_x'])) {
              $modx->setPlaceholder('messagebox', '<p class="warning">You are about to delete this subscriber!  Clicking Delete this below will remove this subscriber from the database permanently.</p><br />');
              $formElements= array (
                  'person' => array (
                      'type' => 'hidden',
                      'name' => 'person',
                      'value' => $person_id,
                  ),
                  'delete' => array (
                      'type' => 'image',
                      'name' => 'delete',
                      'value' => 'Delete this item',
                      'alt' => 'Delete this item',
                      'src' => 'assets/images/delete-this.png',
                      'extra' => ' or <a title="Cancel" href="[~[*id*]~]&person=' . $person_id . '">Cancel</a>',
                  ),
              );
              $makeForm->setFormElements($formElements);
              $personForm= $makeForm->buildForm();
      
              $modx->setPlaceholder('personForm', $personForm);
      
              return $output;
          }
          elseif (isset ($_REQUEST['delete']) || isset ($_REQUEST['delete_x'])) {
              if (isset ($person_id) && is_object($person)) {
                  //NOW ACTUALLY DELETE SOMETHING AND REDIRECT, OR STAY AND PRESENT ERRORS
                  if ($person->remove()) {
                      $modx->sendRedirect($modx->makeUrl($modx->documentObject['parent']));
                  } else {
                      $modx->setPlaceholder('messagebox', '<p class="error">There was an error when attempting to remove this user!  Contact support for assistance if the problem persists.</p>');
                  }
              } else {
                  $modx->setPlaceholder('messagebox', '<p class="error">There was an error when attempting to remove a user!  Contact support for assistance if the problem persists.</p>');
              }
          }
      }
      
      // BUILD YOUR FORM HERE
      $formElements= array (
          'person' => array (
              'type' => 'hidden',
              'name' => 'person',
              'value' => $person_id,
          ),
          'person:first_name' => array (
              'type' => 'text',
              'label' => 'First Name',
              'name' => 'person:first_name',
              'value' => $person->get('first_name'),
              'size' => '50',
              'maxlength' => '100',
          ),
          'person:middle_name' => array (
              'type' => 'text',
              'label' => 'Middle Name',
              'name' => 'person:middle_name',
              'value' => $person->get('middle_name'),
              'size' => '50',
              'maxlength' => '100',
          ),
          'person:last_name' => array (
              'type' => 'text',
              'label' => 'Last Name',
              'name' => 'person:last_name',
              'value' => $person->get('last_name'),
              'size' => '50',
              'maxlength' => '100',
          ),
          'web_users:username' => array (
              'type' => 'text',
              'label' => 'Username',
              'name' => 'web_users:user_name',
              'value' => $webUserId? $webUser['username']: '',
              'size' => '50',
              'maxlength' => '100',
          ),
          'web_users:password' => array (
              'type' => 'password',
              'label' => 'Password',
              'name' => 'web_users:password',
              'value' => $webUserId? $webUser['password']: '',
              'size' => '50',
              'maxlength' => '100',
          ),
          'web_user_attributes:email' => array (
              'type' => 'text',
              'label' => 'Email Address',
              'name' => 'web_user_attributes:email',
              'value' => $webUserId? $webUser['email']: '',
              'size' => '100',
              'maxlength' => '255',
          ),
          'member:expire_date' => array (
              'type' => 'text',
              'label' => 'Member Expiration Date',
              'name' => 'date1',
              'value' => $webUserId? $member->get('expire_date', 'm/d/Y'): strftime('m/d/Y', mktime(0,0,0,date('m'),date('d'),date('Y')+1)),
              'size' => '20',
              'maxlength' => '20',
              'extra' => '<script type="text/javascript" id="js1">var cal1 = new CalendarPopup(\'datediv1\');cal1.showYearNavigation();cal1.showYearNavigationInput();</script><a href="#" onclick="cal1.select(document.forms[0].date1,\'anchor1\',\'MM/dd/yyyy\'); return false;" title="Choose date with calendar" name="anchor1" id="anchor1"><img src="assets/images/calendar.png" alt="[ calendar ]" /></a> <a href="[~102~]#date"><img src="assets/images/help.png" alt="[ help ]" /></a><div style="position:absolute;display:inline;width:180px;height:1px;"><div id="datediv1" style="width:100%;"></div></div>',
          ),
          'address:street' => array (
              'type' => 'text',
              'label' => 'Street Address',
              'name' => 'address:street',
              'value' => $address->get('street'),
              'size' => '80',
              'maxlength' => '255',
          ),
          'address:city' => array (
              'type' => 'text',
              'label' => 'City',
              'name' => 'address:city',
              'value' => $address->get('city'),
              'size' => '80',
              'maxlength' => '255',
          ),
          'address:state' => array (
              'type' => 'select',
              'label' => 'State',
              'name' => 'address:state',
              'options' => $makeForm->createOptions($stateOptions, $address->get('state'), true),
              'size' => '1',
          ),
          'address:zip' => array (
              'type' => 'text',
              'label' => 'Zip',
              'name' => 'address:zip',
              'value' => $address->get('zip'),
              'size' => '10',
              'maxlength' => '20',
          ),
          'address:country' => array (
              'type' => 'hidden',
              'name' => 'address:country',
              'value' => 'USA',
          ),
          'primary_phone:number' => array (
              'type' => 'text',
              'label' => 'Primary phone',
              'name' => 'primary_phone:number',
              'value' => $primaryPhone->get('number'),
              'size' => '20',
              'maxlength' => '20',
          ),
          'secondary_phone:number' => array (
              'type' => 'text',
              'label' => 'Secondary phone',
              'name' => 'secondary_phone:number',
              'value' => $secondaryPhone->get('number'),
              'size' => '20',
              'maxlength' => '20',
          ),
          'save' => array (
              'type' => 'image',
              'name' => 'save',
              'value' => $person_id ? 'Update this item' : 'Add this item',
              'src' => $person_id ? 'assets/images/update-item.png':'assets/images/add-this-item.png',
              'extra' => ' or <a title="Cancel" href="[~[*parent*]~]">Cancel</a>',
          ),
      );
      if ($person_id) {
          $formElements['delete']= array (
              'type' => 'image',
              'name' => 'delete_confirm',
              'value' => 'Delete this item',
              'alt' => 'Delete this item',
              'src' => 'assets/images/delete-this.png',
              'class' => 'rightup',
          );
      }
      
      
      // ETC...
      
      ?>


      And a full page view of the listing is just a matter of creating a target page where you pass a unique identifier from which you can retrieve the data and present it however you so choose.
        • 26289
        • 6 Posts
        Thanks for the reply! I think I have a rough idea now of how it should be done, very nice code. I’m a pretty bad programmer though, I hope I can hack something together.
          • 26289
          • 6 Posts
          Hmmm, I just now read about template variables. This looks very promising. Couldn’t I just define template variables for the post form (Job title, salary range, work from home yes/no), as per these instructions? http://www.modxcms.com/blog-publish.html
          And how would I let the users delete or edit their posts without logging into the manager interface? Would it be possible to search and sort by these template values? Could I include some of the template values in columns of the table? Are there any tricks I can use in MODx to have a dynamically user-sortable table?

          Thanks again for your help!
            • 7231
            • 4,205 Posts
            IMO you could use TV for this, you could also use the default document fields in a clever way and treat each document as a job entry and make the document title the job title, the document description the job description etc... and then add the remaining necessary TVs to complete the data. You can rename the fields in the manager by using the ManagerManger plug-in.

            You can then use Ditto to display the Jobs and tvExplorer to create detailed search and filters.

            tvExplrer: http://modxcms.com/forums/index.php/topic,16456.0/topicseen.html

            To allow editing the user will need to log in as either manager (and use the manager interface), or they can edit as web users via FDM (Frontend Document Manager) which has add and delete features built in (note: it is still officially in beta stage).

            FDM: http://modxcms.com/forums/index.php/topic,14977.0.html

            You could also keep the job data on a custom database table and use your own methods to add edit and delete the data as you would in a conventional home cooked application. But since you say you are not super comfortable coding you may be happier staying within MODx. Remember that currently there is a @5000 document limit in MODx so if you are planning more job listings than that you should use a custom table solution.
              [font=Verdana]Shane Sponagle | [wiki] Snippet Call Anatomy | MODx Developer Blog | [nettuts] Working With a Content Management Framework: MODx

              Something is happening here, but you don&#39;t know what it is.
              Do you, Mr. Jones? - [bob dylan]
              • 26289
              • 6 Posts

              Remember that currently there is a @5000 document limit in MODx so if you are planning more job listings than that you should use a custom table solution

              Ooh, thanks for reminding me. I might eventually have more than 5000 records. In that case, it looks like a custom DB table is the best option, similar to what OpenGeek described. So, in that case, is it searchable by web search engines? And what will the URL look like for each individual item?

              Thanks for the tips!
                • 7231
                • 4,205 Posts
                Not sure about the search engines, I guess that if the data can be accessed then it could be searched but I am only guessing. As for the URL it would look like any other query string url:

                With FURL: www.thedomain.com/somedirectory/somepage?param=value

                Without FURL: www.thedomain.com/index.php?id=10&param=value

                There is a recent post about including the extra parameters in FURL structure but I did not see any solution.
                  [font=Verdana]Shane Sponagle | [wiki] Snippet Call Anatomy | MODx Developer Blog | [nettuts] Working With a Content Management Framework: MODx

                  Something is happening here, but you don&#39;t know what it is.
                  Do you, Mr. Jones? - [bob dylan]