简体   繁体   中英

How do I pass a dynamically created list to the controller to save into the database?

I am working in Concrete5 and am new to the MVC concept. I have a some jquery that creates an unordered list from a textbox in my view. If your familiar with Concrete5 this is the view for the block I am adding the list to. It is basically a list of features for a product. This view needs to save the list to the database base file. Usually this is done pretty simply using a variable that the information gets saved to (aka this is how everything else in the view is saved). The problem I am having is I do not know how to use the controller to pass the unordered list from the view to the controller to the database so that it saves it. Any help and sample code would be appreciated. I'm pretty sure I need to write a php function in my controller to get the list but I am not sure what the code would be.

auto.js

$("#addList").click(function() {
    var text = $("#inputList").val() + '<button>x</button>';
    if(text.length){
        $('<li />', {html: text}).appendTo('ul.featureList')
        };
});
$('ul').on('click','button', function(el){
    $(this).parent().remove()
});

add/edit.php

<div class="ccm-block-field-group">
<h2><?php echo t('Features') ?></h2>

Right now 'features' is the name of the field in my database file db.xml The area featureList is where the list get generated into. I know it needs to be changed around a bit to work, just not sure.

<?php echo $form->textarea('features', $features, array());?>
<input type="test" id="inputList" />
<button type="button" id="addList">Add</button> 
<ul class="featureList"></ul>
</div>

view.php

echo "<h2>{$proName}</h2>";
echo "{$description}";
echo "<h3>{$features}</h3>";
echo "<h2>{$price}</h2>";
echo "<p>{$priceInfo}</p>";

db.xml

<field name="features" type="X2"></field>

With concrete5 blocks, there are two different situations you could be in:

  1. admin user is editing the block (or adding a new block), and you want to save this data to the database.
  2. public user is viewing the block, but the block view itself has a form (for example, a contact form block) and you want to do something when the public form is submitted (for example, send a notification email to an admin that someone has filled out the form, or store the submission in a database for future review).

If you're talking about situation #1, you need to put some custom code in the controller's save() method. If you're talking about situation #2, you need to create your own action method in the controller, AND you need to actually have a <form> in the view.php file.

UPDATE: Based on the sample code you added to your question, here is the solution: The only way your data can get back to the server is via a form POST. <li> elements are not form fields, and hence the data in them doesn't get POST'ed with the form. So when you add the new <li> element to the page, you should also add a hidden form field, like so:

    var listItemCounter = 0;
$("#addList").click(function() {
        listItemCounter++;
    var text = $("#inputList").val() + '<button data-id="' + listItemCounter + '">x</button>'; //assign a unique id number to this button, so it knows which hidden field to remove when clicked
    if(text.length){
        $('<li />', {html: text}).appendTo('ul.featureList');
        $('<input type="hidden" name="features[]" value="' + text + '" data-id="' + listItemCounter + '" />').insertAfter('ul.featureList');
    };
});
$('ul').on('click','button', function(el){
        $('input[data-id="' + $(this).attr('data-id') + '"]').remove(); //remove the hidden field so it does not get POSTed when user saves
    $(this).parent().remove();
});

Now, in your block's controller.php file, you will want to add a save() method that will take all of the data from those hidden fields, combine them and put them into the "features" field that you declared in your db.xml file:

public function save($args) {
    $args['features'] = implode("\n", $args['features']); //combine all feature items into one string, separated by "newline" characters
    parent::save($args);
}

Finally, in your view.php file, you can convert the list of features (which was saved to the database as one string, with each item separated by a "newline" character) like so:

<?php echo nl2br($features); ?>

Or if you want to output it as separate list items, you could do something like this:

<ul>
<?php
$features = explode("\n", $features);
foreach ($features as $feature) {
    echo '<li>' . $feature . '</li>';
}
?>
</ul>

You dont pass stuff from the view to the controller. The controller is executed BEFORE the view, so you only pass from controller to view.

Try accessing the stuff you pass from jquery to your application using

$this->getRequest()->getParam('yourParametersName');

inside the controller.

Lucian

I changed around the auto.js file so it is as follows. Seems to work fine.

var listItemCounter = 0;
$("#addList").click(function() {
    listItemCounter++;
    var text = $("#inputList").val(); //assign a unique id number to this button, so it knows which hidden field to remove when clicked
    var buttonDataId = text + '<button data-id="' + listItemCounter + '">x</button>';
    if(text.length){
        $('<li />', {html: buttonDataId}).appendTo('ul.featureList');
        $('<input type="hidden" name="features[]" value="' + text + '" data-id="' + listItemCounter + '" />').insertAfter('ul.featureList');
        };
});
$('ul').on('click','button', function(el){
    $('input[data-id="' + $(this).attr('data-id') + '"]').remove();//remove the hidden field so it does not get POSTed when user saves
    $(this).parent().remove()
});

I left the view the same as what Jordan Lev put. (Thanks!) Then I changed the controller.php to

public function save($args) { $args['features'] = implode("\\n", $args['features']);//combine all feature items into one string, separated by "newline" characters parent::save($args); }

If anyone sees any problems or a better way to put my code please let me know! My new problem now is once it is saved, if I go to edit the list, it wipes out my past entries and saves the new one. If anyone knows the function I would have to write to show the current list and add to it when editing that would be great. Please give some example code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM