I'm having trouble displaying a view when the user gets authenticated. Why wont a simple ng-show="vm.isLoggedIn" show the view when evaluated to true?
This is my HTML:
<div ng-show="vm.isLoggedIn">
<div ng-view></div>
</div>
This is my Controller:
var MainCtrl = function(userAccount) {
var vm = this;
vm.isLoggedIn = false;
vm.userData = {
userName: "",
email: "",
password: "",
confirmPassword: ""
};
vm.login = function () {
vm.userData.grant_type = "password";
vm.userData.userName = vm.userData.email;
userAccount.login.loginUser(vm.userData, function (data) {
vm.isLoggedIn = true;
vm.message = "";
vm.password = "";
vm.token = data.access_token;
});
}
}
This is the userAccount service I created.
var userAccount = function ($resource, appSettings) {
return {
registration: $resource(appSettings.serverPath + "/api/Account/Register", null,
{
"registerUser": { method: "POST" }
}),
login: $resource(appSettings.serverPath + "/Token", null,
{
"loginUser": {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
transformRequest: function (data, headersGetter) {
var str = [];
for (var d in data) {
str.push(encodeURIComponent(d) + "=" + encodeURIComponent(data[d]));
}
return str.join("&");
}
}
})
}
}
I don't think it has to do with MainCtrl or userAccount, but I included them for context.
Does ng-show prevent any ng-view from being shown? Even if ng-show evaluates to true?
Two things you need to check.
In your html make sure you are using the "controller as" notation and your controller is named as vm:
ng-controller="whateverCtrl as vm"
If you don't do this then vm.isLoggedIn won't evaluate correctly.
make sure your vm.login method is actually called so the flag is actually set to true. You should also set the flag in the controller initially to true to see that the flag actually has the effect you want. Once you see the thing, then turn it to false again and go on from there.
Even if this is probably not the issue I would actually code a flag check like this:
<div ng-show="vm.isLoggedIn === true">
<div ng-view></div>
</div>
you can use ng-include and vm.isLoggedIn can be url when it not false it will be included example:
<button ng-click="vm.isLoggedIn=user==authenticated?'put url hier':false">Include</button>
<div ng-include="vm.isLoggedIn"></div>
Related
I am trying to learn how to work with angular and javascript more. Please let me know what I am doing wrong here.
When I input something into the text box, it should display
"hello {name} , would you like to play a game?
It displays the string without the input.
Also, when I run it, it says
object Object
.
(function (app) {
var JakesController = function ($scope, $http) {
$scope.JakesSampleModel = {name: ' '};
$scope.theSampleReturn = null;
var sendResponseData = function (response) {
if (response.data.error) {
console.log(data);
}
else {
$scope.theSampleReturn = response.data;
}
};
var sendResponseError = function (data) {
console.log(data);
}
$scope.senddata = function (params) {
return $http({
method: 'post',
url: '/home/servercall',
data: params
})
.then(sendResponseData)
.catch(sendResponseError);
};
};
app.controller("JakesController",['$scope', '$http', JakesController]);
}(angular.module("JakesFirstApp")));
Here is the HTML:
<div id="OutterDiv" ng-controller="JakesController" ng-app="JakesFirstApp">
<div id="JakesButton" class="button" ng-click="senddata()">Submit</div>
<input type="text" id="JakesTextBox" ng-model="theSampleReturn" />
{{theSampleReturn.result}}
Json result:
public JsonResult servercall(string name)
{
return Json(new { result = $"Hello {name}, Would you like to play a game?" }, JsonRequestBehavior.AllowGet);
}
In your html try to use {{theSampleReturn}} instead of {{theSampleReturn.result}} because you don't seem to have theSampleReturn.result set anywhere
If I understand you question correctly, then it looks like the solution is to update your template like so:
<input type="text" id="JakesTextBox" ng-model="JakesSampleModel.name" />
And then update your controller to correctly send the name to the server when senddata() is called:
$scope.senddata = function () {
// Construct params for post by getting data from your scope/model that's
// wired up to your input field
var params = { name : $scope.JakesSampleModel.name };
return $http({
method: 'post',
url: '/home/servercall',
data: params
})
.then(sendResponseData)
.catch(sendResponseError);
};
I've a following controller code with me :
var app = angular.module('app_name');
app.controller("manageUsersController", [ "config", "$scope", "$http", "$mdToast",
function(config, $scope, $http, $mdToast) {
$scope.add = function() {
var userData = {
email : $scope.manageUsers.email,
password : $scope.manageUsers.password,
schoolId : '1',
name : $scope.manageUsers.name,
mobileNumber : $scope.manageUsers.mobileNumber
};
$http.post(config.webServicesUrl.postAddUser, userData, headerConfig).success(
function(data) {
displayToastMessage("User added successfully", $mdToast);
}).error(function(error) {
console.log(error.error);
});
}
}]);
All the HTML fields are input fields and are accessed using $scope object.
I tried with $setPristine but it didn't work.
Somebody please help me in setting all the fields to empty upon successful submission of form only in my code.
Thanks.
If you want to reset your form upon completion, I think you have to reset the $scope.manageUsers object manually once your post request has resolve:
$http.post(config.webServicesUrl.postAddUser, userData, headerConfig).success(
function(data) {
// has I don't know if you have other properties
// I reset each property manually,
// but you could probably do $scope.manageUsers = {}
$scope.manageUsers.email = null;
$scope.manageUsers.password = null;
$scope.manageUsers.name = null;
$scope.manageUsers.mobileNumber = null;
displayToastMessage("User added successfully", $mdToast);
}).error(function(error) {
console.log(error.error);
});
You can use $setPristine() here:
$http.post(config.webServicesUrl.postAddUser, userData, headerConfig).success(
function(data) {
displayToastMessage("User added successfully", $mdToast);
$scope.form.$setPristine(); // <---------here.
}).error(function(error) {
console.log(error.error);
});
Plnkr demo in action.
It should work for you.
$http.post(config.webServicesUrl.postAddUser,userData,headerConfig)
.success(function(data) {
$scope.manageUsers={};
displayToastMessage("User added successfully.", $mdToast);
}).error(function(error) {
console.log(error.error);
});
The non-GET instance action $save doesn't work in my example. I always get the Error, that $save is not a function. The problem is, I don't know where I have to define the $scope.example = new Resource();, because in my example I'm using 2 Controllers. One for the table list with objects and the other one for my modal window, where you can take CRUD operations. The CRUD operations are defined in an angular service.
The code is structured as follows:
Servie of Resource:
...
return {
name: $resource(baseUrl + '/api/name/:Id', {
Id: '#Id'
}, {
'update': {
method: 'PUT'
}
}),
...
Service of CRUD:
...
return {
create: function (newName) {
return newName.$save();
},
...
Ctrl of modal window:
$scope.selected = new resService.name();
$scope.createItem = function (newName) {
CrudService.create(newName).then(
function () {
$scope.dataSuccess = 'Person created.';
$scope.newName = null;
},
function (err) {
$scope.dataError = err.data.ModelState;
});
}
}
$scope.form = [{
label: 'Firstname',
fieldType: 'text',
name: 'Fname',
id: 'fname-id',
propertyName: 'fname',
disabled: false,
pattern: /^[a-zA-Z]{4}[a-zA-Z]*/,
required: true,
errRequired: 'Firstname is required.',
errPattern: 'Firstname has at least 4 letters.'
},
...];
The view with form:
<form class="form-horizontal" name="editForm" novalidate>
<div class="form-group-sm has-feedback" ng-repeat="elem in form" ng-class="{ 'has-error' : hasError(editForm, elem.name), 'has-success' : hasSuccess(editForm, elem.name) }">
<label class="control-label" for="{{elem.id}}">{{elem.label}}</label>
<input type="{{elem.fieldType}}"
class="form-control"
placeholder="{{elem.label}}"
name="{{elem.name}}"
id="{{elem.id}}"
ng-model="selected[elem.propertyName]"
ng-disabled="{{elem.disabled}}"
ng-pattern="elem.pattern"
ng-required="{{elem.required}}"
/>
<p class="help-block" ng-if="elem.errRequired" ng-show="editForm[elem.name].$error.required && editForm[elem.name].$touched">{{elem.errRequired}}</p>
<p class="help-block" ng-if="elem.errPattern" ng-show="editForm[elem.name].$error.pattern">{{elem.errPattern}}</p>
EDIT:
I'm getting a new Error. The console tells, that I have to use track by expression. But I was trying to use the form view without generating and then works. But I need the generated form view (the example view above).
Error Message:
Error: ngRepeat:dupes
Duplicate Key in Repeater
Duplicates in a repeater are not allowed. Use 'track by' expression to specify unique keys.
If you wan't to create a new object you need the choose the service between the Services choice (factory, service, providers).
The difference between a factory and a service, is about syntax. Just syntax.
.factory(function(){
//Private variables and functions
var x = "ez";
function getX(){
return x;
}
//Public functions (or variables)
return {
a : "test",
getA : function(){
return a;
}
}
})
//Service example
.service(function(){
//Handled by Angular:
//new() is used to create a new object
//Private functions and variables
var x = "test";
function getX(){
return x;
}
//Public funcitons (and variables)
this.a = function(){
"test";
};
this.getA = function(){
return a;
};
//Handeled by AngularJS
//return this;
});
Everything that is returned in the factory is available.
The service automaticaly creates a new object when calling it, which makes available the object ("this")
Calling a service or a factory remains the same:
var a = service.getA();
var a = factory.getA();
EDIT
Notice also that you can decide if your promise is going to the next error or success call.
Just as an exmaple:
xhr()
.then(success1, error1)
.then(success2, error2)
.then(success3, error3)
...
success and error are all callback functions.
By using $q you can go to the next success or error, wathever the callback.
QUESTION CODE
. factory ( 'YourFacotry' , [ '$resource' ,
function ( $resource ) {
return $resource ( '/api/note/:id' , { id : '#id' },
{
markAsDone :
{
url : '/api/note/:id/done' ,
method : 'POST' ,
isArray : true
}
});
}]);
Ctrl of modal window:
$scope.createItem = function () { //Forgot $scope here!
CrudService.query().then(
function () {
$scope.dataSuccess = 'Person created';
$scope.newName = null;
},
function (err) {
$scope.dataError = err.data.ModelState;
});
}
}
I have a custom directive for soundcloud that requires the soundcloud url. The soundcloud url is fetched from the database through the $http service, however, the div for the soundcloud custom directive is loaded and requires the value of the soundcloud url before it is even defined.
The Plangular Directive Code I got is here:
https://github.com/jxnblk/plangular/blob/master/src/plangular.js *I did not develop this
This is my HTML code:
<div plangular="{{soundcloud}}">
<button ng-click="playPause()">Play/Pause</button>
<progress ng-value="currentTime / duration || 0">
{{ currentTime / duration || 0 }}
</progress>
</div>
And this is the Angular Code:
displaySong.controller('song', ['$scope', '$http', 'fetchSong', function($scope, $http, fetchSong) {
$scope.songID
$scope.songName;
//Controller properties
$scope.songPromise; //The song promise for fetching
$scope.init = function(songID, userID) {
$scope.songID = songID;
$scope.userID = userID;
$scope.songPromise = $http({
method: "post",
url: fetchSong,
data: {
song_id: $scope.songID
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).then(function(successResponse) {
console.log('Successfully fetched song');
console.log(successResponse);
var song = successResponse.data;
$scope.songID = song.song_id;
$scope.songName = song.song_name;
$scope.songType = song.song_type;
$scope.songEmbed = song.song_embed;
$scope.soundcloud = song.song_embed;
}, function(errorResponse) {
console.log('Error fetching');
$scope.songID = null;
});
};
}]);
I know it's a problem with the asynchronous nature because when I add this line in the beginning of my song controller:
$scope.soundcloud = "https://soundcloud.com/jshigley/shine";
It works perfectly fine. I've also noticed that when I spam the play/pause button that DOES come up from the directive, I get multiple console errors of "HTTP 404 Not Found", which leads me to believe it's trying to find a track of undefined url
Since it's a div directive and not a function call I can't use promises such as chaining a then to my $scope.songPromise. I've thought of putting it into a controller and having the controller do something like $timeout for 5 seconds, but I don't think this delays the execution of the DOM.
The soundcloud URL DOES end up getting loaded, but it remains undefined in the eyes of the plangular directive (I've actually encountered lots of these problems with bad timing of loading scope and directives). Any Angular Wizards willing to teach me how to tame the asynchronous nature of AngularJS?
You can use $watch in the custom directive to watch when url attributes is changed.
In
link: function(scope, el, attr) {
change from
if (src) {
resolve({ url: src, client_id: client_id }, function(err, res) {
if (err) { console.error(err); }
scope.$apply(function() {
scope.track = createSrc(res);
if (Array.isArray(res)) {
scope.tracks = res.map(function(track) {
return createSrc(track);
});
} else if (res.tracks) {
scope.playlist = res;
scope.tracks = res.tracks.map(function(track) {
return createSrc(track);
});
}
});
});
}
to
scope.$watch('attr.plangular', function(newVal) {
resolve({ url: attr.plangular, client_id: client_id }, function(err, res) {
if (err) { console.error(err); }
scope.$apply(function() {
scope.track = createSrc(res);
if (Array.isArray(res)) {
scope.tracks = res.map(function(track) {
return createSrc(track);
});
} else if (res.tracks) {
scope.playlist = res;
scope.tracks = res.tracks.map(function(track) {
return createSrc(track);
});
}
});
});
}, true);
If you dont want to change the directive then you might want to use ng-if to load that plangular div only when you get the url.
<div plangular="{{soundcloud}}" ng-if="haveurl">
and in the angular code :
}).then(function(successResponse) {
console.log('Successfully fetched song');
console.log(successResponse);
$scope.haveurl = true;
Try using ng-show like this to only show the div once your $http request has been completed.
<div ng-show="httpRequestComplete" plangular="{{soundcloud}}">
<button ng-click="playPause()">Play/Pause</button>
<progress ng-value="currentTime / duration || 0">
{{ currentTime / duration || 0 }}
</progress>
</div>
displaySong.controller('song', ['$scope', '$q', '$http', 'fetchSong', function($scope, $http, fetchSong) {
/* add $q promise library */
$scope.songID
$scope.songName;
var httpRequest = function() {
var deferred = $q.defer();
$http({
method: "post",
url: fetchSong,
data: {
song_id: $scope.songID
},
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}).success(function(successResponse) {
deferred.resolve({response: successResponse});
console.log('Successfully fetched song', successResponse);
var song = successResponse.data;
$scope.songID = song.song_id;
$scope.songName = song.song_name;
$scope.songType = song.song_type;
$scope.songEmbed = song.song_embed;
$scope.soundcloud = song.song_embed;
}).error(function(error) {
console.log(error);
});
return deferred.promise;
};
httpRequest().then(function(response) {
$scope.httpRequestComplete = true;
console.log('div will show');
};
}]);
I would do something like this that delays the showing of the div until httpRequestComplete = true, or until your promise ($q) is fulfilled. This will make sure that your div isn't loaded until you have the information available.
i am using the below format to get a JSON object from my localhost. The JSON is pretty complicated and lengthy so , using jquery to populate the HTML is getting complicated.
function processmsg(msg) {
var jobj = JSON.parse(msg);
if (typeof jobj === 'object')
{
// Parse the JSON
}
document.getElementById("messages").innerHTML = globalTag;
}
}
function waitForMsg() {
$.ajax({
type: "GET",
url: "1.json",
cache: false,
timeout: 50000,
success: function (data) {
processmsg(data);
if (!data) {
setTimeout(
waitForMsg,
1000
);
};
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
setTimeout(waitForMsg, 15000);
processmsg("error");
}
});
};
$(document).ready(function () {
waitForMsg();
processmsg("loading");
});
I would like to use the format like {{jobj.entries}}. something like this. This can be done on angularJS. can you guys please suggest me how to do the same in angular ?
i want to query the JSON every 1 min and when the data is found i want to cancel the interval. I dono how to do it in angularjs.
==================update================
i got below code snippet. It is working fine, But how do i stop the url query once the json object is obtained..
var app = angular.module('urlanalyzer', []);
app.controller('jsonController', function($scope, $http) {
$scope.getData = function(){
var url = "{% static "" %}tmp/{{url_hash}}/{{url_json}}";
$http.get(url)
.success(function(data, status, headers, config) {
console.log(data);
});
};
if (!$scope.data){
setInterval($scope.getData, 2000);
}
The issue here is the json object will be available after 3 sec only.
var app = angular.module('urlanalyzer', []);
app.controller('jsonController', ['$scope','$http','$timeout',function($scope, $http, $timeout) {
$scope.getData = function(){
var url = "{% static "" %}tmp/{{url_hash}}/{{url_json}}";
$http.get(url)
.success(function(data, status, headers, config) {
if(!data)
$timeout(function(){
$scope.getData()
}, 2000)
else{
$scope.myData = data.data? data.data:data;
$scope.showError = false;
}
})
.error(function(msg) {
$timeout(function(){
$scope.getData()
}, 2000)
$scope.processMessage(msg)
});
};
$scope.processMessage = function(msg){
if(angular.isString(msg))
$scope.errorMessage = msg;
else if(angular.isObject(msg)){
$scope.errorMessage = msg.message // the property you want;
}
$scope.showError = true;
}
$scope.getData();
}])
HTML:
<div ng-controller="jsonController">
<div ng-show="showError">
{{errorMessage}}
</div>
<div id="myDatacontainer">
//you can bind any propery of your data by using angular direvtives
//look at ng-bing, ng-if etc. directives
{{myData.name}} ...
</div>
</div>
Hope it help.
Consider you have following JSON data stored in a scope variable named data:
$scope.data = {
"array": [
1,
2,
3
],
"boolean": true,
"null": null,
"number": 123,
"object": {
"a": "b",
"c": "d",
"e": "f"
},
"string": "Hello World"
}
Then you write your HTML in the following way like:
<div>
Boolean: {{data.boolean}}
</div>
<div>
Number: {{data.number * 2}}
</div>
<div>
Array:
<p ng-repeat="(key, value) in data.object"> {{key}} : {{value}}</p>
</div>
Another way to bind <div ng-bind="data.string"></div>
Here you can stop your call. You can use enhanced angular service $interval for this:
$scope.getData = function(){
var url = "{% static "" %}tmp/{{url_hash}}/{{url_json}}";
$http.get(url)
.success(function(data, status, headers, config) {
console.log(data);
$interval.cancel($scope.intervalObject); // cancel the interval when data is loaded
});
};
if (!$scope.data){
$scope.intervalObject = $interval($scope.getData, 2000);
}
if (!$scope.data){
setInterval($scope.getData, 2000);
}
since $scope.data is not set it'll continue calling the request(since you are not setting $scope.data anywhere).
Edit: Also, use angularjs $interval since it's the angular way of using setInterval and it keeps track of the $digest cycle