0

I have angular working in one of my ASP.NET MVC applications. I am using two html templates with Angular Routing. One is a list of current Favorites that comes from the database and is serialized into json from my Web API and used by angular to list those items from the database.

The second html template is a form that will be used to add new favorites. When the overall page that includes my angular code loads, it has a cookie named currentSearch which is holding the value of whatever the last search parameters executed by the user.

I would like to inject this value into my angular html template (newFavoriteView.html) for the value of a hidden input named and id'd searchString.

I have tried using jQuery, but had problems, plus I would much rather do this inside of angular and somehow pass the value along to my template or do the work inside the view(template). However, I know the latter would be bad form. Below is the code I think is important for one to see in order to understand what I am doing.

Index.cshtml (My ASP.NET VIEW)

@{
    ViewBag.Title = "Render Search";
    ViewBag.InitModule = "renderIndex";
}
    <div class="medium-12 column">
        <div data-ng-view=""></div>
    </div>
@section ngScripts {
    <script src="~/ng-modules/render-index.js"></script>
}

Setting the cookie in the MVC Controller

    private void LastSearch()
    {
        string lastSearch = null;
        if (Request.Url != null)
        {
            var currentSearch = Request.Url.LocalPath + "?" + 
                                    Request.QueryString;

            if (Request.Cookies["currentSearch"] != null)
            {
                lastSearch = Request.Cookies["currentSearch"].Value;
                ViewBag.LastSearch = lastSearch;
            }

            if (lastSearch != currentSearch)
            {
                var current = new HttpCookie("currentSearch", currentSearch){ 
                                   Expires = DateTime.Now.AddDays(1) };
                Response.Cookies.Set(current);

                var previous = new HttpCookie("lastSearch", lastSearch) { 
                                   Expires = DateTime.Now.AddDays(1) };
                Response.Cookies.Set(previous);
            }
        }
    }

render-index.js

angular
    .module("renderIndex", ["ngRoute"])
    .config(config)
    .controller("favoritesController", favoritesController)
    .controller("newFavoriteController", newFavoriteController);

function config($routeProvider) {
    $routeProvider
        .when("/", {
            templateUrl: "/ng-templates/favoritesView.html",
            controller: "favoritesController",
            controllerAs: "vm"
        })
        .when("/newsearch", {
            templateUrl: "/ng-templates/newFavoriteView.html",
            controller: "newFavoriteController",
            controllerAs: "vm"
        })
        .otherwise({ redirectTo: "/" });
};

function favoritesController($http) {
    var vm = this;
    vm.searches = [];
    vm.isBusy = true;

    $http.get("/api/favorites")
        .success(function (result) {
            vm.searches = result;
        })
        .error(function () {
            alert('error/failed');
        })
        .then(function () {
            vm.isBusy = false;
        });
};

function newFavoriteController($http, $window) {
    var vm = this;
    vm.newFavorite = {};
    vm.save = function () {
        $http.post("/api/favorites", vm.newFavorite)
            .success(function (result) {
                var newFavorite = result.data;
                //TODO: merge with existing topics
                alert("Thanks for your post");
            })
            .error(function () {
                alert("Your broken, go fix yourself!");
            })
            .then(function () {
                $window.location = "#/";
            });
    };
};

favoritesView.html

<div class="container">
    <h3>New Favorite</h3>
    <form name="newFavoriteForm" ng-submit="vm.save()">
    <fieldset>
      <div class="row">
        <div class="medium-12 column">
          <input name="searchString" id="searchString" type="hidden" 
                 ng-model="vm.newFavorite.searchString"/>
            <label for="title">Name</label><br />
              <input name="title" type="text" 
                     ng-model="vm.newFavorite.name"/>
                <label for="title">Description</label><br />
                <textarea name="body" rows="5" cols="30" 
                          ng-model="vm.newTopic.description"></textarea>
              </div>
              <div class="medium-12 column">
                <input type="submit" class="tiny button radius" value="Save"/> | 
                <a href="/" class="tiny button radius">Cancel</a>
              </div>
          </div>
      </fieldset>
  </form>
</div>

My current attepts have been using jQuery at the end of the page after Angular has loaded and grab the cookie and stuff it in the hidden value. But I was not able to get that to work. I also thought about setting the value as a javascript variable (in my c# page) and then using that variable in angular some how. AM I going about this the right way?

Or should it be handled in the angular controller?...

I'm new to angular and the Angular Scope and a bit of ignorance are getting in the way. If any other info is needed I can make it available, thanks if you can help or guide me in the right direction.

Eric Bishard
  • 5,201
  • 7
  • 51
  • 75

2 Answers2

1

Sorry if I'm misunderstanding or over-simplifying, but...assuming JavaScript can read this cookie-value, you could just have your controller read it and assign it to a $scope variable?

If JavaScript can't read the value, then you could have your ASP write the value to a JavaScript inline script tag. This feels yuckier though.

Update to show controller-as example.

Assuming your HTML looked something vaguely like this:

<div ng-controller="MyController as controller">
  <!-- other HTML goes here -->
  <input name="searchString" id="searchString" type="hidden" ng-model="controller.data.currentSearch"/>

Then your controller may look something like this:

app.controller('MyController', function ($scope, $cookies) {
  $scope.data = {
    currentSearch: $cookies.currentSearch
  };
  // Note that the model is nested in a 'data' object to ensure that
  // any ngIf (or similar) directives in your HTML pass by reference
  // instead of value (so 2-way binding works).
});
bvaughn
  • 13,300
  • 45
  • 46
  • Any possibility anyone could expand on this answer using ControllerAs? – Eric Bishard Feb 26 '15 at 02:32
  • Sure. I updated the answer to show a controller-as example. I didn't actually run it, so please pardon any typos. – bvaughn Feb 26 '15 at 02:51
  • Ok, Im understanding now. but I'm trying to leave the $scope out of my code and bind the cookie value to `this.` but I think I have it now. I will update my code with the final solution. – Eric Bishard Feb 26 '15 at 03:27
  • I'll update my code in a few with my final solution. Funny how all three of us kinda worked off each other to figure this out. I thought I knew angular well until I started trying to get rid of $scope and use ControllerAs in 1.3+ projects. Also trying to make sure I'm using the techniques from the angular style guide. – Eric Bishard Feb 26 '15 at 03:41
  • It's kind of funny. I have a semi-popular angular project (Angular formFor) but I haven't really written an Angular website in at least 6 months because I've been doing Android development. So I feel a bit out-of-touch with Angular. I haven't even used 1.3 yet. :) – bvaughn Feb 26 '15 at 03:45
1

You can do it by reading the cookie value using JavaScript, set it as a property of the $scope object and access it on the template.

//Inside your controllers
function favoritesController($http, $scope) {
    //Get the cookie value using Js
    var cookie = document.cookie; //the value is returned as a semi-colon separated key-value string, so split the string and get the important value

    //Say the cookie string returned is 'currentSearch=AngularJS'
    //Split the string and extract the cookie value

    cookie = cookie.split("="); //I am assuming there's only one cookie set

    //make the cookie available on $scope, can be accessed in templates now
    $scope.searchString = cookie[1];
}

EXTRA NOTE In AngularJS, the scope is the glue between your application's controllers and your view. The controller and the view share this scope object. The scope is like the model of your application. Since both the controller and the view share the same scope object, it can be used to communicate between the two. The scope can contain the data and the functions that will run in the view. Take note that every controller has its own scope. The $scope object must be injected into the controller if you want to access it.

For example:

//inject $http and $scope so you can use them in the controller
function favoritesController($http, $scope) {

Whatever is stored on the scope can be accessed on the view and the value of a scope property can also be set from the view. The scope object is important for Angular's two-way data binding.

Akinkunle Allen
  • 1,299
  • 12
  • 19
  • Thank you for using it in the context of the controller. Sorry for the delayed response, had to take my son to the library. lol What about the fact that I'm using ControllerAs and not $scope? I think that is where I am confused. – Eric Bishard Feb 25 '15 at 23:54
  • Ok, I'm messing with it, but you may figure it out before me. so I appreciate any help. Again, still a bit new to Angular and understanding scope and ($scope) as well as making sure it's somewhat efficient. – Eric Bishard Feb 26 '15 at 00:07
  • Thanks, sometimes we just need a good example! I understand perfectly now. I do appreciate your help. – Eric Bishard Feb 26 '15 at 00:43
  • There is more than one cookie set. The one I am trying to get the value of is `cookies.currentSearch` – Eric Bishard Feb 26 '15 at 01:09
  • @EricB Check out this link: http://stackoverflow.com/questions/10730362/get-cookie-by-name – Akinkunle Allen Feb 26 '15 at 01:53