Three condition button based on Angular - javascript

I am fairly new to Angular an I am feeling lost in all of it's documentation.
Problem:
I am trying to create a button which has three phases:
Add User - Remove Request - Remove User
So if you want to add a user you click on the Add button, which
sends an ajax request to the server and if successful the button
should then turn into a Pending button.
In the pending state if you click on it again, your request will be
deleted and it will again turn back to a Add button.
The third phase is also if the user has accepted your request, you
will be seeing a Remove user button which when you click on
you will again see the Add button which if you click you will get
the Pending button and so forth.
So basically it is a familiar button if you've been using social networks.
When the page is loaded the user will see the users and the buttons for each user based on it's current condition (so the server will be handling this part). From this part Angular should handle the ajax calls and changing of the button per user connection request.
What I need:
I have done the Ajax part for sending the request. However I can't manage to handle the part which Angular needs to change the button to it's new state (for a specific user on the list, meaning the list has more than 1 user which you can send connection add/pending/delete requests.) I have tried different solutions but failed till now.
Some of my messy failure code which I have left unfinished:
Angular Controller:
foundationApp.controller('ConnectionButtonCtrl', function ($scope, $http) {
$scope.addUser = function(id) {
$http({
method : 'GET',
url : '/api/connections/add/'+id,
dataType: "html",
})
.success(function() {
$scope.activeId;
$scope.activeId = id;
$scope.isAdd = function(id){
return $scope.activeId === id;
};
})
};
$scope.removeRequest = function(id) {
$http({
method : 'GET',
url : '/api/connections/removeRequest/'+id,
dataType: "html",
})
.success(function() {
})
};
});
Laravel Blade View:
<span ng-controller="ConnectionButtonCtrl" >
<a class="label radius fi-plus" ng-show="!isRemove(1)" ng-click="addUser(1)"></a>
<a class="label radius fi-clock info" ng-show="isRemove(1)" ng-click="removeRequest(1)"></a>
<a class="label radius fi-x alert" ng-show="!isAdd(1)" ng-click="removeUser(1)"></a>
</span>

If I understand correctly, just use $index or user.id. I am assuming your buttons are on the same line as the user. If that's true then you are probably using an ng-repeat.
For example:
<div ng-repeat="user in users">
<a class="label radius fi-plus" ng-show="!isRemove(user.id)" ng-click="addUser(user.id)"></a>
<a class="label radius fi-clock info" ng-show="isRemove(user.id)" ng-click="removeRequest(user.id)"></a>
<a class="label radius fi-x alert" ng-show="!isAdd(user.id)" ng-click="removeUser(user.id)"></a>
<div> some user information {{user.name}} </div>
</div>
Then you can pass the id of the user with your ajax request. You can also use $index (as a parameter in my code instead for the index of the user in the array).

DEMO: http://plnkr.co/edit/hhOdNTV6ogJHhtXcM03a?p=preview
js
var app = angular.module('myApp', []);
app.controller('myController', function ($scope) {
$scope.users = {
user1: {
'status': 'add',
'statusClass': 'positive'
},
user2: {
'status': 'pending',
'statusClass': 'waiting'
},
user3: {
'status': 'remove',
'statusClass': 'negative'
}
};
$scope.handle = function (user) {
if (user.status === 'add') {
alert('send request to the user');
user.status = 'pending';
user.statusClass = 'waiting'
}
else if (user.status === 'pending') {
alert('send request to discard a connection req');
user.status = 'add';
user.statusClass = 'positive'
}
else {
alert('send req for removal');
user.status = 'add';
user.statusClass = 'positive'
}
};
});
app.$inject = ['$scope'];
HTML:
<body ng-app="myApp" ng-controller="myController">
<div ng-repeat="user in users">
User {{$index+1}} - <button ng-click="handle(user)" ng-class="user.statusClass">{{ user.status }}</button>
</div>
</body>
http://plnkr.co/edit/hhOdNTV6ogJHhtXcM03a?p=preview

Related

Current page using Angular

I have a "Remove All" button that removes all records from a Ng-table and MongoDB.
In my system, there are several views and each and every one of them display different data. Now, I don't know how to get the current page name and send it as a parameter for remove. It is working only if I insert to the code the name of the view and click on the button.
HTML:
<ul class="pager" ng-show="currentPage==login">
<li>
<button ng-click="removeLogs('$scope.logType')" id="deleteAllErrors" name="deleteError" class="btn btn-danger">Remove All</button></li>
</ul>
Angular:
// login, signUp, addErr, refreshLog, refreshErr, badProd - $scope.currentPage
$scope.removeLogs = function(logType){
console.log("Admin request to delete logType: "+logType+" & "+currentPage.current.name);
var rmLogs = {
'email': localStorageService.get('email'),
'password': localStorageService.get('password'),
'logType': logType
};
$http.post(''+appPath+'/removeLogs', rmLogs)
.then(function(data){
$scope.statusMsg = "Logs Deleted Successfully";
console.log("Admin X has delete logType");
$scope.updateAdmin();
});
};
You can inject $route in controller's DI and access the params like this.
var currentMethod = $route.current.params.name;
Or you can use $routeParams https://docs.angularjs.org/api/ngRoute/service/$routeParams

ng-repeat does not update the html

I am new to Angular and need your help on an issue with the ng-repeat of my app.
Issue:
I have an html page (event.html) and in the corresponding controller of the file, I make a request to a firebase collection and update an array ($scope.events). The issue is that the data from firebase takes a few seconds to load and by the time data arrives to $scope.events, ng-repeat has already been executed and it displays an empty screen. The items are displayed correctly the moment I hit on a button in the HTML page (event.html).
Sequence of events:
I have a login page (login.html) where I enter a user name and phone number and I click on the register button. I've configured this click on the register button to go to the new state (event.html).
Here is the controller code for login.html:
$scope.register = function (user) {
$scope.user = user.name;
$scope.phonenumber = user.phonenumber;
var myuser = users.child($scope.user);
myuser.set({
phone : $scope.phonenumber,
Eventid : " ",
name : $scope.user
})
var userid = myuser.key();
console.log('id is ' +userid);
$state.go('event');
}
The controller of event.html (the state: event) has the following code:
var ref = new Firebase("https://glowing-torch-9862.firebaseio.com/Users/Anson/Eventid/");
var eventref = new Firebase("https://glowing-torch-9862.firebaseio.com/Events");
var myevent = " ";
$scope.events = [];
$scope.displayEvent = function (Eventid) {
UserData.eventDescription(Eventid)
//UserData.getDesc()
$state.go('myevents');
//console.log(Eventid);
};
function listEvent(myevents) {
$scope.events.push(myevents);
console.log("pushed to array");
console.log($scope.events);
};
function updateEvents(myevents) {
EventService.getEvent(myevents);
//console.log("success");
};
ref.once('value', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
$scope.id = childSnapshot.val();
angular.forEach($scope.id, function(key) {
eventref.orderByChild("Eventid").equalTo(key).on("child_added", function(snapshot) {
myevents = snapshot.val();
console.log(myevents) // testing 26 Feb
listEvent(myevents);
updateEvents(myevents);
});
});
});
});
$scope.createEvent = function () {
$state.go('list');
}
event.html contains the following code:
<ion-view view-title="Events">
<ion-nav-buttons side="primary">
<button class="button" ng-click="createEvent()">Create Event</button>
<button class="button" ng-click="showEvent()">Show Event</button>
</ion-nav-buttons>
<ion-content class="has-header padding">
<div class="list">
<ion-item align="center" >
<button class= "button button-block button-light" ng-repeat="event in events" ng-click="displayEvent(event.Eventid)"/>
{{event.Description}}
</ion-item>
</div>
</ion-content>
</ion-view>
The button showEvent is a dummy button that I added to the HTML file to test ng-repeat. I can see in the console that the data takes about 2 secs to download from firebase and if I click on the 'Show Events' button after the data is loaded, ng-repeat works as expected. It appears to me that when ng-repeat operates on the array $scope.events, the data is not retrieved from firebase and hence its empty and therefore, it does not have any data to render to the HTML file. ng-repeat works as expected when I click the dummy button ('Show Event') because a digest cycle is triggerred on that click. My apologies for this lengthy post and would be really thankful if any of you could give me a direction to overcome this issue. I've been hunting in the internet and in stackoverflow and came across a number of blogs&threads which gives me an idea of what the issue is but I am not able to make my code work.
Once you update your events array call $scope.$apply(); or execute the code that changes the events array as a callback of the $scope.$apply function
$scope.$apply(function(){
$scope.events.push(<enter_your_new_events_name>);
})
If you are working outside of controller scope, like in services, directive, or any external JS. You will need to trigger digest cycle after change in data.
You can trigger digest cycle by
$scope.$digest(); or using $scope.$apply();
I hope it will be help you.
thanks
In your case you have to delay the binding time. Use $timeout function or ng-options with debounce property in your view.
you have to set a rough time taken to get the data from the rest API call. By using any one of the methods below will resolve your issue.
Method 1:
var myapp = angular.module("myapp", []);
myapp.controller("DIController", function($scope, $timeout){
$scope.callAtTimeout = function() {
console.log("$scope.callAtTimeout - Timeout occurred");
}
$timeout( function(){ $scope.callAtTimeout(); }, 3000);
});
Method 2:
// in your view
<input type="text" name="userName"
ng-model="user.name"
ng-model-options="{ debounce: 1000 }" />

Update ng-repeat values in angular js

I am listing some elements and each element has a click event and as a parameter the same element.
<a class="item item-avatar item-lista" ng-click="verView({{$index}},{{view}})">
Function verView :
$scope.verView = function(index,view){
sessionService.set("view_leido",view);
$location.path("/event/view/"+index);
}
Function darLike:
$scope.darLike = function(view_id, index){
console.log(UrlService.url+'likeView/'+sessionService.get("user_id")+'/'+sessionService.get("hash")+"/"+view_id+"/");
$http({method: 'GET', url: UrlService.url+'likeView/'+sessionService.get("user_id")+'/'+sessionService.get("hash")+"/"+view_id+"/"})
.success(function(data){
if(data.status == 1){
angular.copy(data.view.TableView, $scope.views[index]);
}
})
.error(function(){
})
.finally(function(){
});
}
These elements can be given LIKE this creates a record in my database and return the number of Likes having my element, so I update my object in the list. But while sending object parameter arrives outdated, for example:
If you would LIKE to one that has 0 likes, stay at 1 like, when you click and view detail I get 0 likes yet.

AngularJS : Communication between directives - ng-repeat not refresh

I apologize of a mess but this is the first time on stackoverflow ;)
Link to jsfiddle
http://jsfiddle.net/1u1oujmu/19/
I have problem with communication between directives and refresh ng-repeat.
I have two pages homePage and dashboardPage - on these page I have directive when I refresh page (dashboardPage) everything is working, but when I switch on homePage and I will back to dahsboardPage my problem starts occurs.
Step reproduce:
dashboardPage - reload - add new link - list-link directive is refresh new link is on list
go to homePage
back to dashboard page
try to add new link - when link is added (on server and I receives response) I call factory to store a data:
dataFactory.editData("userLinksList", result.data);
//part of factory to edit and propagation data
editData: function(name, data){
dataArray[name] = data;
$rootScope.$broadcast(name);
},
Then in directive controller I have condition to listen propagation "userLinksList" checkRootScope this is flag for only one register listener
Problem is in line:
$scope.data.links = dataFactory.getData("userLinksList");
In $scope.data.links I receives new data but I don't know why ng-repeat is not refresh
when I go to homePage and back to dashboard new link will be on list
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
homePage - on the page I have list-link directive:
<div class="columns marketing-grid">
<div class="col-md-6">
<list-link hp="true"></list-link>
</div>
</div>
dashboardPage - on the page I have this same directive without parameter:
<div class="row">
<div class="col-sm-12 col-md-8">
<list-link></list-link>
</div>
</div>
template of list-link:
<ul ng-if="data.links">
<li ng-repeat="link in data.links | filter: search" class="link-list-item" data-id="{{link.id}}">
<div class="row">
<div class="col-md-9">
<a ng-href="link.url"><h3>{{link.title}} <span>{{link.host}}</span></h3></a>
</div>
<div class="col-md-3 link-list-time text-right">
{{link.date | date : 'd/MM/yyyy' }}
</div>
<div class="col-md-12">
<blockquote ng-show="link.comment">{{link.comment}}</blockquote>
</div>
<div class="col-md-2">
<span class="link-list-counter all" title="Number of links">{{link.counterAll}}</span>
</div>
<div class="col-md-6 link-list-tags">
<span>tags:</span>
<ul ng-if="link.tags">
<li ng-repeat="item in link.tags">#{{item}}</li>
</ul>
</div>
<div class="col-md-4 text-right link-list-buttons">
<button class="btn btn-default btn-xs" title="Edit" ng-click="edit(link.id);">Edit <span class="glyphicon glyphicon-edit" aria-hidden="true"></span></button>
<button class="btn btn-default btn-xs" title="Delete" ng-click="delete(link.id);">Delete <span class="glyphicon glyphicon-remove" aria-hidden="true"></span></button>
</div>
</div>
</li>
</ul>
Directive list-link:
app.directive("listLink", ['path', function(path){
var path = path.url(),
checkRootScope = true;
return {
restrict : "E",
scope : {
hp : "="
},
templateUrl: path.template.listlink,
replace : true,
transclude : false,
controller : ['$rootScope', '$scope','conn', 'auth', 'loaderService','stringOperation','dataFactory', function($rootScope, $scope, conn, auth, loaderService, stringOperation,dataFactory){
var dataConenction = function(){
conn.getData(path.server.link, { params : $scope.data })
.then(function(result){
if($scope.data.all == true){
dataFactory.addData("popularLinksList",result.data);
$scope.data.links = dataFactory.getData("popularLinksList");
} else{
dataFactory.addData("userLinksList",result.data);
$scope.data.links = dataFactory.getData("userLinksList");
}
}, function(msg){
console.log(msg);
});
};
$scope.hp = (typeof $scope.hp === "undefined" ? false : $scope.hp);
$scope.path = path;
$scope.userInfo = auth.getUserInfo();
$scope.data = {
auth : $scope.userInfo,
check : false,
all : $scope.hp
};
dataConenction();
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
$scope.edit = function(id){
$rootScope.$broadcast("editLink", {"id": id});
};
$scope.delete = function(id){
var check = confirm("Are you sure you want to remove?");
if (check == true) {
conn.deleteData(path.server.link, {"params" : {auth : $scope.userInfo, id : id}})
.then(function(result){
dataFactory.editData("userLinksList",result.data.links);
$scope.data.links = dataFactory.getData("userLinksList");
dataFactory.editData("userTagsList",result.data.tags);
}, function(msg){
console.log(msg);
});
}
};
}]
}
}]);
Not sure if you already fixed it but I had a crack at it.
First the "why not working" part -
Page1 creates a new scope, lets say scope1.
Page2 creates a new scope, say scope2.
When the Page1 is clicked the data.link is set to 5 items and below code is run [scope1.data.link = 5 items] -
if(checkRootScope){
$rootScope.$on("userLinksList", function () {
$scope.data.links = dataFactory.getData("userLinksList");
});
checkRootScope = false;
}
When the Page2 is clicked, it set 7 items to dataFactory and it is broadcasted to and $rootScope.on is executed to update scope2.data.links to 7 items. However scope2.data.links is still set to 5 items. This is because when $rootScope.on is executed first time the "$scope" variable within the "on" function refers to closure scope i.e scope1 and NOT scope2. So essentially when scope.data.links is set to 7 then scope.data.links is set to 7 and scope2.data.links is still set to 5.
Basically ng-view creates a new scope and if directive is part of each of the views, you would always end up having different data.link value in each of the views.
Solution:
You can fix it in two ways:
Option 1: You would be better off setting the value in scope as soon the promise is resolved instead of setting in factory and getting from it in $on listener. Atleast in this case.
http://plnkr.co/edit/IdrsO1OT9zDqdRiaSBho?p=preview
Option 2: If broadcast is really essentially I think you would have to bind the data.link to rootscope (which might not be a good practice).
http://plnkr.co/edit/VptbSKRf7crU3qqNyF3i?p=preview
and may be there are other options...

Angularjs pass data in between services that exist on different pages

I have a simple book store example that I am working through for angularjs and I am trying to pass a book id from a home page into a service on an edit page so that the book details can be rendered. What I have happen is I can see the rest call being hit from my home' page with the correct book id being passed into the book service. However, I cannot seem to think of a way to have theBookCtrl` load that data when a different page invokes the rest service. The order I am expecting is:
1) User enters a book ID to edit
2) User presses Search button
3) book.html page is loaded
4) BookEdit service is invoked with ID from Steps 1 and 2
5) ng-model for book loads data.
Apologies in advance, there may be some errors as I was modifying this code from a different computer, so I couldn't copy/paste
code below:
home.html
<div ng-controller="HomeCtrl">
<div>
<label for="query">Book to edit</label>
<input id="query" ng-model ="editBook.query">
<button ng-click="loadBookById()">Search</button>
</div>
</div>
home.js:
var homeApp = angular.module('bookHome',['bookEdit']);
homeApp.controller('HomeCtrl',function($scope,$http,bookEditService)
{
$http.get('http://get/your/books/rest').success(function(data){
$scope.library = data;
});
$scope.editBook = {
query: '',
service:'bookEditService'
} ;
$scope.loadBookById = function()
{
$scope.$emit('loadBookById',{
query:$scope.editBook.query,
$service: $scope.editBook .service
}
$scope.$on('loadBookById', function(ev,search){
bookEditService.loadBook({
bookId: $scope.editBook.query
},
$scope.searchComplete,
$scope.errorSearching
);
});
$scope.searchComplete = function(results) {
$scope.results = results;
};
$scope.errorSearch= function(data,status,headers,config){
console.log(data);
// ...
};
}
book.html
<div ng-controller="BookCtrl" >
<div ng-model="details.title"></div>
<div ng-model="details.author"></div>
</div>
bookEdit.js
var bookEditApp = angular.module('bookEdit',[]);
bookEditApp.service('loadBook',function($http){
return{
loadBookById: function(params,success,error){
$http({
url: 'http://path/to/book/editing',
method: 'GET',
params:{bookId: params.bookId}).success(function(data,status,headers,config)
{
var results = data;
success(results || []);
}).error(function(){
error(arguments);
});
}
};
});
bookEditApp.controller('BookCtrl',function($scope){
$scope.details = {
title: "",
author: ""
};
});
An alternative that follows the order you are expecting is:
1) User enters book id and presses button
2) HomeCtrl routes to EditCtrl with the entered id as a route parameter (no need to use the book service yet):
app.controller('HomeCtrl', function ($scope, $location) {
$scope.editBook = function () {
$location.path('/edit/' + $scope.id);
};
});
3) EditCtrl is loaded, retrieves the route parameter and asks the book service for the correct book:
app.controller('EditCtrl', function EditCtrl($scope, $routeParams, bookService, $location) {
$scope.loading = true;
bookService.getBookById($routeParams.id)
.then(function (result) {
$scope.book = result;
$scope.loading = false;
});
4) When book is loaded the model ($scope.book) is populated and the html is updated
Here is a working example that hopefully will give some further guidance and ideas: http://plnkr.co/edit/fpxtAU?p=preview

Categories

Resources