4

I have a mysql database with the tables "deliverables", "tags" and "deliverables_has_tags". I want to link tags to a deliverable.

This is what I do in my javascript file:

<script type="text/javascript" language="javascript">
    $(function () {
        var object = {};
        $.ajax({
            type: "GET",
            url: "/Deliverable/Tags",
            dataType: "json",
            success: function (data) {
                object.tags = data;
            }
        });

        function split(val) {
            return val.split(/,\s*/);
        }
        function extractLast(term) {
            return split(term).pop();
        }
        $("#tags")
        // don't navigate away from the field on tab when selecting an item
            .bind("keydown", function (event) {
                if (event.keyCode === $.ui.keyCode.TAB &&
                $(this).data("ui-autocomplete").menu.active) {
                    event.preventDefault();
                }
            })

.autocomplete({
    minLength: 0,
    source: function (request, response) {
        // delegate back to autocomplete, but extract the last term
        response($.ui.autocomplete.filter(
object.tags, extractLast(request.term)));
    },
    focus: function () {
        // prevent value inserted on focus
        return false;
    },
    select: function (event, ui) {
        var terms = split(this.value);
        // remove the current input
        terms.pop();
        // add the selected item
        terms.push(ui.item.value);
        // add placeholder to get the comma-and-space at the end
        terms.push("");
        this.value = terms.join(", ");

        return false;
    }
});
    });
</script>

I can add multiple tags in my textbox.

But now I want to save this in my repository. In my Action method in controller:

repository.AddDeliverable(model.Title, model.Description, model.UsernameID, data, datatwo, model.VideoUrl, model.AfstudeerrichtingID, model.ProjectID);

Tags action:

public JsonResult Tags()
{
    var data = (repository.GetTags()).ToArray();

    return Json(data, JsonRequestBehavior.AllowGet);
}

In my repository:

public IQueryable<string> GetTags()
{
    return from tag in entities.tags
           orderby tag.tag_name
           select tag.tag_name;
}

I have no clue how to save this in my database.
Can anybody help me?

nielsv
  • 6,540
  • 35
  • 111
  • 215
  • There is a way to model-bind a `serializeArray()`'d collection, see [http://stackoverflow.com/questions/4402036/jquery-ajax-posting-array-to-asp-net-mvc-controller/4402080#4402080](http://stackoverflow.com/questions/4402036/jquery-ajax-posting-array-to-asp-net-mvc-controller/4402080#4402080) – OzrenTkalcecKrznaric Jun 16 '13 at 16:10

2 Answers2

2

If I correctly understood your question, you have implemented your tag handling as follows:

  1. There is MVC action method that returns the view with input placeholder containing no data
  2. The placeholder itself is probably input type=text with id=tags
  3. On 'dom ready' you fire ajax request to retrieve your tags from database, json-serialized as array; when it arrives you store it to tags variable (no error handling(!))
  4. At the same time you decorate your input with jqueryui autocomplete that reacts on user input and returns items from the tags variable
  5. Since input already contains tags (comma separated), your filter is first letters of the last tag

So, you have a situation when user has input a few comma separated tags (probably some of them can be new) and now wants to save it to the database. For each input, if that is a known tag you have to store it to "deliverables_has_tags". If there is a new tag, you have to store it both to "tags" and "deliverables_has_tags".

Most common scenario would be having a 'Save' button to start saving process. Let's analyze what you have to do in the process.

1) Button click

On button click you use js to convert your comma separated tags string using logic like split(term) to the array, and serialize it. You can do serialization using serializeArray and manually create JSON object, or serialize the whole form using $('#yourForm').serialize(). I would choose the first option because that way I get more control over JSON format and avoid problems with MVC default model binder.

2) Ajax call

When the JSON object is ready to be sent, you fire an ajax POST request to your MVC POST action method. When you save state always avoid GET because new versions of browsers can scan thru your page and actively preload urls using GET requests. You don't want this here. Of course, use your data as a data-parameter in the ajax call.

3) Action method

When the request arrives, you have to process it in your controller using a new action method. Typically in this case you will have something like public JsonResult SaveTags(SaveTagsModel saveTags) { ... } which saves tags using your repository and returns result that says something like 'OK' or 'ERROR' (sth like response.isSaved=true/false). Tricky part can be designing view model according to your JSON object - this could help. And regarding collections this could be valuable info.

When saving, use transaction to ensure everything is saved at once. First check if each tag exists in the database and insert those who don't exist. After that, check for each tag if there is appropriate n-n relation in deliverables_has_tags and insert it if there isn't. I believe that you should use same repository encapsulation for both operations.

Community
  • 1
  • 1
OzrenTkalcecKrznaric
  • 5,535
  • 4
  • 34
  • 57
1

In the post action, include FormCollection collection as argument and gather your tags from that. There is no automatic way. You could implement some custom model binding, but that is probably not worth the effort.

Jeroen K
  • 10,258
  • 5
  • 41
  • 40