-2

I have an actionlink which triggers a function in the view controller, the function moves a file from one folder to an "archive" folder, so it doesn't return anything. However when the button is clicked the function fires and the correct file is moved but the view changes to "/functionName + variables", I need the page to stay the same and for just the function to run. Ideally not with a work around of having the page refresh/re-direct back to itself.

The button is in an ng-repeat as the files can change, there is also a button to download the file this fires and the file is downloaded, no view change etc occurs.

<div ng-repeat="file in toFileList">
    @{
        var toURL = Url.Action("DownloadFile", "Home", new { ToFrom = "to", FileName = "{{toFileList[$index][0]}}"});
        toURL = HttpUtility.UrlDecode(toURL);
    }
    @{
        var toArchiveURL = Url.Action("ArchiveFile", "Home", new { ToFrom = "to", FileName = "{{toFileList[$index][0]}}" });
        toArchiveURL = HttpUtility.UrlDecode(toArchiveURL);
    }

    <a style="text-decoration: none;" data-ng-href="@toURL">
        <span class="glyphicon glyphicon-download-alt"></span>
    </a>
    <a style="text-decoration: none;" data-ng-href="@toArchiveURL">
        <span class="glyphicon glyphicon-eye-open"></span>
    </a>
</div>

I construct the actionlink URLs then apply them to each button using data-ng-href

The function is a void as it doesn't return anything unlike the file download function which is of ActionResult type.

public void ArchiveFile(string ToFrom, string FileName)
        {
            string path = BaseFolder + client + @"\" + ToFrom + @"\" + FileName;
            string destinationPath = BaseFolder + client + @"\" + ToFrom + @"\Archive\" + FileName;

            byte[] fileBytes = System.IO.File.ReadAllBytes(path);

            System.IO.File.Move(path, destinationPath);
        }

I've tried adding "id="something" to the {} containing the action variables and then adding the following to the bottom of the page (The below was taken from another similar question on here)

<script>
        $("#something").click(function (e) {
            e.preventDefault();
            $.ajax({
                url: $(this).attr("href"),
                success: function () {
                    alert("clicked"); 
                }

            });

        });
    </script>

But this results in nothing happening

EDIT: I have also also tried the js/ajax id on tag and the within with same results.

Vereonix
  • 1,341
  • 5
  • 27
  • 54
  • So, amid all of this, are you just trying to tell us that your `.click()` handler isn't preventind the default click action? (Also, side note... `"comma here instead of semicolon"` - You don't really need comments to indicate that your code is syntactically correct.) – David May 21 '18 at 14:46
  • 1
    1) if you add an id to something which repeats, then you'll end up with duplicate IDs, which won't work for anything except the first element to which the ID is added. 2) it's the hyperlink you'd have to add a selector to, because that's the thing that's clicked, 3) if this markup is being repeated by Angular then it won't exist until a later time in the execution, so you'd have to delay binding the event until that code has all run. Probably Angular has a solution to this, from what I've read jQuery and Angular don't make good pals. – ADyson May 21 '18 at 14:47
  • 1
    Actually I'm somewhat surprised this works at all (even without ajax) - what does the Razor code (executed server-side) make of the `"{{toFileList[$index][0]}}"` string, which is a variable populated on the client side? I don't see how it could evaluate it correctly. Also that Razor code will only ever execute once, not repeat itself for each file. – ADyson May 21 '18 at 14:49
  • @ADyson The razor repeats just fine and has no issue with the angular values... Why wouldn't it work? – Vereonix May 21 '18 at 14:52
  • 1
    because Razor is executed server-side before the Javascript values are ever computed, or the JS execution environment even exists. Unless I have missed something? Admittedly I'm no Angular expert but I do understand it's a client-side JS framework. Is there some server-side magic at work here related to Angular which isn't apparent from your snippet? – ADyson May 21 '18 at 14:55
  • 1
    As far as I can see your `toArchiveURL` Razor variable ought to look like `http://www.example.com/ControllerName/ArchiveFile?toFrom=to&FileName={{toFileList[$index][0]}}` How can it possibly evaluate `{{toFileList[$index][0]}}` on the server, if that's a client-side variable? Or is the magic that Angular interprets that because it's already injected into the "data" attribute as part of the URL? I guess that must be it. Whatever, the actual Razor code will _not_ be executed repeatedly, it is outside the execution context of the ng-repeat loop. – ADyson May 21 '18 at 14:57
  • 1
    I'm terribly curious about this selector: `$("#something")` What/where is `#something`? Does it exist when that jQuery selector executes? Do you have more than one element in the DOM with the same ID? There's a variety of reasons this could fail, and they seem to center around this weird mix of frameworks you have here. But at the very least, if you have multiple elements with the same `id` then your HTML is invalid. And if your elements don't exist when the jQuery selector executes then it won't attach a click handler at all. – David May 21 '18 at 14:57

1 Answers1

1

As I'm using Angular I changed it so I call the c# controller function in the js instead.

HTML:

<div style="float:left" ng-click="archiveFile(toFileList[$index][0])">
   <span class="glyphicon glyphicon-eye-open"></span>
</div>

I use ng-click to call the angular in the .js controller

JS:

$scope.archiveFile = function (fileName) {    
  $http.get("/Home/ArchiveFile", { params: { ToFrom: "To", FileName: fileName } }).then(function (result) {
      console.log(result)
  });
};

Here I give a scope name which is what the ng-click references, and pass the params the c# function needs. This triggers the function and doesn't try to change the view.

Vereonix
  • 1,341
  • 5
  • 27
  • 54