Ng-model with Cookie - javascript

I'm trying to take the first example from the angular.js homepage and adding in cookie support.
This is what I have so far: https://jsfiddle.net/y7dxa6n8/8/
It is:
<div ng-app="myApp">
<div ng-controller="MyController as mc">
<label>Name:</label>
<input type="text" ng-model="mc.user" placeholder="Enter a name here">
<hr>
<h1>Hello {{mc.user}}!</h1>
</div>
</div>
var myApp = angular.module('myApp', ['ngCookies']);
myApp.controller('MyController', [function($cookies) {
this.getCookieValue = function () {
$cookies.put('user', this.user);
return $cookies.get('user');
}
this.user = this.getCookieValue();
}]);
But it's not working, ive been trying to learn angular.
Thanks

I'd suggest you create a service as such in the app module:
app.service('shareDataService', ['$cookieStore', function ($cookieStore) {
var _setAppData = function (key, data) { //userId, userName) {
$cookieStore.put(key, data);
};
var _getAppData = function (key) {
var appData = $cookieStore.get(key);
return appData;
};
return {
setAppData: _setAppData,
getAppData: _getAppData
};
}]);
Inject the shareDataService in the controller to set and get cookie value
as:
//set
var userData = { 'userId': $scope.userId, 'userName': $scope.userName };
shareDataService.setAppData('userData', userData);
//get
var sharedUserData = shareDataService.getAppData('userData');
$scope.userId = sharedUserData.userId;
$scope.userName = sharedUserData.userName;
Working Fiddle: https://jsfiddle.net/y7dxa6n8/10/
I have used the cookie service between two controllers. Fill out the text box to see how it gets utilized.

ok, examined your code once again, and here is your answer
https://jsfiddle.net/wz3kgak3/
problem - wrong syntax: notice definition of controller, not using [] as second parameter
If you are using [] in controller, you must use it this way:
myApp.controller('MyController', ['$cookies', function($cookies) {
....
}]);
this "long" format is javascript uglyfier safe, when param $cookies will become a or b or so, and will be inaccessible as $cookies, so you are telling that controller: "first parameter in my function is cookies
problem: you are using angular 1.3.x, there is no method PUT or GET in $cookies, that methods are avalaible only in angular 1.4+, so you need to use it old way: $cookies.user = 'something'; and getter: var something = $cookies.user;
problem - you are not storing that cookie value, model is updated, but cookie is not automatically binded, so use $watch for watching changes in user and store it:
$watch('user', function(newValue) {
$cookies.user = newValues;
});
or do it via some event (click, submit or i dont know where)
EDIT: full working example with $scope
https://jsfiddle.net/mwcxv820/

Related

Populate ng model from value

I am trying to populate the ng-model from a value, but don't want it to update until it is saved. To do this I have the following code;
Controller;
var SettingsController = function (roleService) {
var ctrl = this;
ctrl.rename = function(name) {
ctrl.account.name = name;
};
roleService.role.settings().then(function (result) {
ctrl.account = result.data.account;
}, function (result) {
console.log(result);
});
};
A simple controller, it gets the current settings from a service and sets it to the ctrl.
When the rename(name) is called I update the name of the account (for now it just updates the scope but soon it will update also the back-end)
To rename your account I have the following piece of code
<input type="text" data-ng-model="account.name" />
<button type="button" data-ng-click="ctrl.rename(account.name)">
Rename
</button>
I use controler as so ctrl == SettingsController
Now I use data-ng-model="account.name" to update the name. This is done so I only update the name when the button is called. The only issue is how do I get the ctrl.account.name value to the input, without bubbling it up.
I could add $scope to my controller with $scope.account but that seems overkill to me. Isn't there a way to copy/populate a ng-model from an other value or some kind?
To get to the controller I use the angular routerProvider;
$routeProvider
.when('/settings/', {
templateUrl: '/user/template/settings/',
controller: 'SettingsController',
controllerAs: 'ctrl'
});

Use http cookie value in an Angular template

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"/> |
Cancel
</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.
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.
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).
});

Empty Kendo-Editor from angular controller

I am using kendo ui richtextbox on one of my pages:
<textarea kendo-editor rows="3" cols="4" ng-model="fooData.Answer" id="answerInput" placeholder="blablablabla" class="form-control" k-encoded="false"></textarea>
In my controller I have:
function ($scope, $sce, Foo) {
$scope.foos = [];
$scope.fooData = kendo.observable();
$scope.addFoo = function (fooData) {
Foo.create(fooData)
.success(function (data) {
$scope.fooData = kendo.observable();
$scope.foos.push(data);
});
}
Which adds an item foo to a collection using an api, which all works like a charm. The thing that does not work is that the kendo-editor does not get emptied. The input remains. In the documentation they stated that you should use kendo.observables, which I do, but to no avail.
Any ideas?
Apparetnly I just needed to do
$scope.fooData.Answer = "";
$scope.fooData.Question = "";
in my addFoo function.

Angular JS get value into another variable

I have $scope.user = {} when I do this <input type="text" ng-model="user.name">the name in the input gets stored into $scope.user how do I get that value into another variable?
var myApp = angular.module('myApp', []);
myApp.controller('WizardController', ['$scope', function($scope){
$scope.user = {};
$scope.displayName = $scope.user{'name'};
}]);
I think you meant:
$scope.displayName = $scope.user.name
or
$scope.displayName = $scope.user['name']
Also, if you want to display the value of '$scope.user.name' somewhere in your html (which is what I assume you're trying to do) you can do something like this:
<h2>{{user.name}}</h2>
EDIT
If you want it to automatically refresh $scope.displayName in your view when you update $scope.user.name you'll need to add this to your controller:
$scope.$watch('user.name', function () {
$scope.displayName = $scope.user.name;
});
However, there's probably very few good reasons to do it that way.
Fiddle: http://jsfiddle.net/HB7LU/3752/ (Updated from one in comment to include logging).
If you want to put it in another variable you just have to make a new one.
$scope.newName = $scope.user.name;
The content will be put into the newName scope. Is that what you mean?
$scope.displayName = $scope.user{'name'}; I think you want to rewrite it to:
$scope.displayName = $scope.user.name or $scope.user['name'];

Client side duplicate data validation in angularJS

I'm trying to figure out if it is possible to validate data client side to ensure that no duplicates are sent to the database. I have an angular app which gets data from an api call. This is my current controller for adding a new subject (functioning perfectly, but without data validation):
angular.module('myApp.controllers')
.controller('SubjectNewCtrl', ['$scope', 'SubjectsFactory', '$location', '$route',
function ($scope, SubjectsFactory, $location, $route) {
// callback for ng-click 'createNewSubject':
$scope.createNewSubject = function () {
SubjectsFactory.create($scope.subjects);
$location.path('/subjects');
}
}]);
And here is what I have been attempting for data validation:
angular.module('myApp.controllers')
.controller('SubjectNewCtrl', ['$scope', 'SubjectsFactory', '$location', '$route',
function ($scope, SubjectsFactory, $location, $route) {
// callback for ng-click 'createNewUser':
$scope.createNewSubject = function () {
var newSubject = $scope.subject.name;
var someSubject = $scope.subjects;
var oldSubject;
if(newSubject){
angular.forEach($scope.subjects, function(allSubjects){
if(newSubject.toLowerCase() == allSubjects.name.toLowerCase()){
oldSubject = true;
}
});
if (!oldSubject){
SubjectsFactory.create($scope.subjects);
}
}
}
}]);
This gives me a console error- TypeError: Cannot read property 'name' of undefined. How do I access the 'name' property of my new subject from the html? Can anyone tell me if what I am trying to do is possible/ makes sense?
If I understand your question correctly, you should use a directive for the specific field you are trying to validate. A unique email directive would be a common example. Here is one I have used in the past. Nothing fancy.
MyApp.directive('uniqueEmail', ['$http', function($http) {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ctrl) {
//set the initial value as soon as the input comes into focus
element.on('focus', function() {
if (!scope.initialValue) {
scope.initialValue = ctrl.$viewValue;
}
});
element.on('blur', function() {
if (ctrl.$viewValue != scope.initialValue) {
var dataUrl = attrs.url + "?email=" + ctrl.$viewValue;
//you could also inject and use your 'Factory' to make call
$http.get(dataUrl).success(function(data) {
ctrl.$setValidity('isunique', data.result);
}).error(function(data, status) {
//handle server error
});
}
});
}
};
}]);
Then in your markup you could use it like so.
<input type="text" name="email" ng-model="item.email" data-unique-email="" data-url="/api/check-unique-email" />
<span class="validation-error" ng-show="form.email.$error.isunique && form.email.$dirty">Duplicate Email</span>
Hope this is what you were looking for.
I have implemented object creation in Angular js many times.
My createNew button method typically just created a new javascript Object() and set the scope.currentObject to the new Object();
In your case it appears that $scope.subject is not initialized to anything, hence the error.
I guess that there must be a html input on your form that is bound the subject.name field but without a subject Object to hold the name it is effectively unbound.
If I wanted users to enter a name then click create button to validate that the name is not used. I would bind the new Name input to a different $scope variable (perhaps $scope.newName)
Then in the createNewSubject method you can actually create a new subject like this:
$scope.subject = new Object();
$scope.subject.name = $scope.newName;
Then you can run your validation code.

Categories

Resources