Angular it taking the old parameter when clicking button - javascript

I am trying to add a button which when clicked, calls a function which takes a parameter and sends it to my server. So far it looks like this:
<table class="table table-hover">
<thead>
<tr>
<th>Id</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="interview in $ctrl.pendingInterviews">
<td>{{ interview.id }}</td>
<td><input type="submit" name="Submit" id="submit" ng-click="$ctrl.addParticipant();"></td>
</tr>
</tbody>
</table>
What I have in my angular component:
var participant={
username:"mama",
interviewId:$routeParams.interviewId
};
console.log(participant);
console.log(JSON.stringify(participant));
this.addParticipant = function saveParticipant() {
console.log("in partikip")
Interview.addParticipant(JSON.stringify(participant))
.then(
function (errResponse) {
console.error('Error while fetching pending interviews');
}
);
}
And what I have in my angular service:
function addParticipant(participant) {
console.log("Im here too");
console.log(participant + "asdasdsda");
var deferred = $q.defer();
$http.post('http://localhost:8080/interviewsupdateparticipant', participant)
.then(
function (response) {
deferred.resolve(response.data);
},
function (errResponse) {
console.error('Error while adding participant');
console.error(''+ participant.username + participant.interviewId)
deferred.reject(errResponse);
}
);
return deferred.promise;
}
The problem is that first when I go to my page, participant from the controller has the username set to mama and the interviewId set to undefined. When I click the submit button, instead of sending the id and the hardcoded username, it sends undefined and the hardcoded username. Why? Why doesn't it automatically get the interviewId?
The moment I click Submit, the id stays undefined for some reason and it only changes if I click again. Any ideas what the problem could be?

Many things that could solve this:
Try using ngHref instead of just href when you have variable part of your url
Try passing the interview.id as a parameter to your addParticipant() method instead of getting it via the $routeParams variable
You have an input type="submit" outside any form, and inside an <a> link, try changing that

Related

How to get a cell value from an html table to use in an axios request in reactjs?

I have a HTML table of clients, and I want to be able to delete one of them thanks to a simple axios delete request. In order to do that, I have to get the ID of the client I want to delete.
So here is what I did :
async function deleteClient(e) {
e.preventDefault();
const id = document.getElementById("client").innerHTML;
console.log(id);
axios
.delete("http://localhost:8080/api/clients/" + id)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
}
The deleteClient function is called onClick in the table. The issue is, it only ever gets the ID of the first row client and never the one from rows below. What can I do to get the right ID and be able to delete other clients ?
For info, here is my HTML table, it is filled dynamically thanks to useEffect hook and a simple axios get request :
<table className="text-white border-2 border-bikeexplogray-light rounded-full">
<tr>
<th>Clients</th>
</tr>
<tr>
<th>ID</th>
<th>Store Name</th>
<th>Username</th>
<th>Email</th>
<th>Phone number</th>
<th>Address</th>
<th>Zipcode</th>
<th>City</th>
<th>Website</th>
<th>Delete</th>
</tr>{" "}
{filteredData.map((value, index) => {
return (
<tr key={value.id}>
<td id="client">{value.id}</td>
<td>{value.storeName}</td>
<td>{value.username}</td>
<td>{value.email}</td>
<td>{value.phone}</td>
<td>{value.adress}</td>
<td>{value.zipcode}</td>
<td>{value.city}</td>
<td>{value.website}</td>
<td>
<button onClick={deleteClient}>Delete</button>
</td>
</tr>
Thanks in advance for the help!
The id attribute on the td tag must be unique within the document.
You can use data-id instead, data-* is just a standard way to attach data to the DOM.
In your event handler deleteClient you can use e.currentTarget to access the context.
function deleteClient(e) {
// this will be your button element
const button = e.currentTarget
// search up the DOM tree (each parent) for this selector match
const td = button.closest("tr > td[data-id]")
// this should be the ID from the data-* attribute
console.log(td.dataset.id)
// ...
}
You can easily get the id of the customer you want to delete because you are in a map() function. Each one of your rows have a unical key that is equal to value.id, so you can modify the button as follows to do the trick :
<button onClick={(e) => deleteClient(e, value.id)}>Delete</button>
And don't forget to modify your deleteClient function :
async function deleteClient(e, id) {
e.preventDefault();
//const id = document.getElementById("client").innerHTML;
console.log(id);
axios
.delete("http://localhost:8080/api/clients/" + id)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
}

Implement Search Functionality Node JS/MySQL

Having some trouble properly implementing a search filter by the Pokemon Name on my Node JS/MySQL DB. When I search I am getting "search/?key=undefined 404 (Not Found)" Any ideas? Here is my search route
router.get('/search', function(req, res){
var mysql = req.app.get('mysql');
var sql='SELECT pokemonname FROM pokemon WHERE pokemonname LIKE "%' + req.key.query + '%';
sql = mysql.pool.query(sql, function(error, results, fields) {
if(error) {
res.write(JSON.stringify(error));
res.end();
} else {
res.status(200);
res.end();
}
});
});
Here is my handlebars file to render the search bar/search button
<table id="table">
<thead>
<th>Pokemon Name </th>
<th>Evolution Level </th>
<th>Move Name </th>
</thead>
<input type="text" class="search form-control" id="searchinput" placeholder="Pokemon Name">
<input type="button" class="btn btn-primary" value="Search" onclick="getUsers({{id}})"/>
<br>
<tbody>
{{#each pokemon}}
<tr>
<td>{{pokemonname}}</td>
<td>{{evolutionlevel}}</td>
<td>{{movename}}</td>
<td><button onclick="deletePokemon({{id}})">Delete</td>
<td>Update</td>
</tr>
{{/each}}
</tbody>
And finally my search.js function in JQuery
function getUsers(searchinput){
$.ajax({
type: 'GET',
url: '/search/?key=' + searchinput,
success: function(result){
window.location.reload(true);
}
})
};
Thanks for the help
Most occurences of {{id}} are used inside #each loop suggesting id is property of pokemon object. Meanwhile your getUser({{id}}) is used outside of this loop leading to undefined passed to binding variable id. I think that you want to pass value of text input to your getUser function instead, hence your name of formal parameter e.g. searchinput. You could use {{input value=searchinput}} from Ember helper and then getUser({{searchinput}}) in your button. Also pay attenttion to encoding query params passed to called AJAX service.

Retrieving the id from Model to Controller in Angular JS

i have a table which is having the data retrieved from an api call from my memberController which is displayed inside ng-repeat and its working fine.
I need each Business Name of the member list to link to a separate page(edit_form.html) and display the id value, so that i can pass this along with the api call to get only this particular member detail. So i have added ng-init in my edit form page which calls the function test_funct when the page loads and retrieve each persons id there. unfortunately i am unable to retrieve the id value inside the function.
HTML Template
<div class="page" data-ng-controller="memberController">
<table>
<thead >
<tr>
<th>Business Name</th>
<th>Contact Name</th>
<th>Trade Balance</th>
<th>Cash Balance</th>
<th>Telephone</th>
<th>Account Number </th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="member in details | filter:search">
<td>{{member.businessname}}</td>
<td>{{member.person}}</td>
<td>{{member.balance_trade}}</td>
<td>{{member.balance_cash}}</td>
<td>{{member.telephone}}</td>
<td>{{member.accountnumber}}</td>
</tr>
</tbody>
</table>
</div>
I have the following controller
function memberController($scope, $http, $cookieStore) {
var token = $cookieStore.get('token');
var conId = $cookieStore.get('Cont_Id');
var exId = $cookieStore.get('ex_Id');
var member_list = "http://www.vb.com/functions/member_list.html?exchangeid=" + exId +
"&contactid=" + conId + "&token=" + token;
$http.get(member_list)
.success(function(response) {
$scope.details = response;
});
$scope.test_funct = function(id) {
$scope.myid = id;
alert($scope.myid); // getting undefined in alert, i expect the id(eg:1123)
}
}
edit_form.html
<div class="page" data-ng-controller="memberController">
<div class="panel-body" ng-init="test_funct()"></div>
</div>
Please assist me on this. Thanks in advance.
There are 2 things going on here.
First, you should separate controllers for the different views, so you end up with something like this:
<div class="page" data-ng-controller="memberController">
<table>
<!-- your whole big table here -->
</table>
</div>
And your editing form as follows:
<div class="page" data-ng-controller="editController">
<div class="panel-body"></div>
</div>
Notice that you now have two distinct controllers - your "editController" and your "memberController".
The second question then becomes, how do you transfer the selected ID from the list view ("memberController") to the edit view ("editController").
There are 2 ways of doing that.
First, you could use a service shared between the controller:
.factory('SelectedId',function() {
return {};
});
And then in your "member" view, you would set it upon clicking:
{{member.businessname}}
Notice the ng-click, which then needs a function in the memberController and the injected service:
.controller('memberController',function($scope,SelectedId) {
$scope.setId = function(id) {
SelectedId.id = id;
};
});
While the editController retrieves it:
.controller('editController',function($scope,SelectedId) {
$scope.id = SelectedId.id;
});
The above option works well, especially for complex things like shopping carts. If all you are doing is passing an ID, I would just stick it in the URL:
{{member.businessname}}
So that the ID is part of the URL. You then can retrieve it in the "editController":
.controller('editController',function($scope,$routeParams) {
$scope.id = $routeParams.member;
});
assuming you are using ng-route, and your route would look like:
$routeProvider.when('/pages/edit_form/:member',{templateUrl:'/route/to/template.html',controller:'editController'});
In html do that
<td>{{member.businessname}}</td>
...
In app.js or where you define route do that
.when('/edit/:memberid',
{
templateUrl:'partials/edit.html',
controller:'editController'
})
In controller you have to take this id by doing that
app.controller("editController",function($routeParams,$scope){
$scope.memberid= $routeParams.memberid;
//Now use this member id to fetch all data
});

ng-class directive call executed twice

Simple html:
<table class="table table-condensed">
<tr data-ng-repeat="customer in customers" data-ng-class="customerSelectedClass(customer)">
<td>
{{customer.Name}}
</td>
</tr>
</table>
In my controller - two functions to select customer and return proper class to highlight a table row:
$scope.customerSelectedClass = function (customer) {
if (customer == $scope.selectedCustomer) {
console.log('returing info for ' + customer.Name);
return "info";
}
return "";
};
$scope.selectCustomer = function (customer) {
console.log('selecting ' + customer.Name);
$scope.selectedCustomer = customer;
}
I noticed that when I click on a customer link, customerSelectedClass function executes twice. selectCustomer function on ng-click directive executes once, as it should. Angular is only included once on the page. I wonder if this is a bug in Angular or something that I am doing wrong?
Behind the scenes, angular is setting up a $watch on the function that is resolving the class name. Because angular uses dirty checking to see if there has been a change, this method will be called twice during the $digest cycle. This is ok.
I would suggest that you don't add this code the the controller though, because if you are managing many css classes, you could be adding a lot of unnecessary code. Try something like this instead:
<table class="table table-condensed">
<tr data-ng-repeat="customer in customers" data-ng-class="{'info': customer == selectedCustomer}">
<td>
{{customer.Name}}
</td>
</tr>
</table>
Then, there is no need for a controller function customerSelectedClass. This will only add the info class if the right-hand side of the : resolves to true. And there is no problem resolving the correct customer in the ng-repeat.
Hope this helps.

Durandal. Pass additional data to other view

I've got a view that needs to be populated conditionally.
Scenario:
A manager will select a users name on screen B, then will be navigated to the same form the user filled in EG. screen A, except that the said manager will have the option to approve or deny the request of the user.
I've seen that in my VM on screen A I can do the following.
var vm = {
activate: function (data) {
console.log(data);
var id = data.id || -1;
if (id !== -1) {
router.isNavigating(true);
http.json('/api/user/'+ id )
.done(function (response) {
ko.viewmodel.updateFromModel(vm.userInfo, response);
router.isNavigating(false);
});
}
}
};
And then B (view & view model)
view
<table>
<thead>
<tr>
<td>User</td>
<td>Date Requested</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<tr>
<td>Mike</td>
<td>19 Jun 2013
</td>
<td>
<input type="button" value="Go" data-bind="click: function() { buttons.goTo(6) }" />
</td>
</tr>
</tbody>
</table>
viewmodel
define(['durandal/plugins/router'], function (router) {
var buttons = {
goTo: function (id) {
console.log('goTo clicked');
//this does work in conjunction with my code on B
router.navigateTo('#/userinfo?id=' + id);
}
};
var vm = {
buttons: buttons
};
return vm;
});
My issue is that I'm not sure what the best way/or how to for that matter to get Durandal to navigate to page A from B... Is what I'm doing right? As it feels a little bit "hacky"
The navigation, at least to me, is designed to mimic standard MVC web navigation. In this case, since you already know that you want to go to 6, why not use an anchor like so
<a href="#/userinfo?id=6"/>
A better way would be to register your route with an id splat like so your route would become
routes.map({route: 'userinfo/:id, ...
<a href="#/userinfo/6" />
This way you can access the splat on the activate method..there are several examples out there but I don't have links to them. Basically the activate method of your userinfo viewmodel will accept a parameter and from there you can load an entity or whatever you like. Hope this helps.
Brad

Categories

Resources