Update exiting element ng-repeat list in angularjs? - javascript

I made task table through the ng-repeat, Each task in table can can be modify. Task table will have to updated with updated task. So for this we need to access particular ng-repeat element. I want to know how to access particular ng-repeat element and update this with new task ng-click=editTask().
Please see $scope.editTask, Here I want to update inside $http.put(uri, data).
Workflow:
ng-click=beginTask(task) opens dialog, In dialog there is ng-click=editTask(), which will modify the task through $http.put...
Please see DEMO
<tr ng-repeat="task in tasks">
<td>{{task.title}}</td>
<td>{{task.description}}</td>
<td>
<a class="btn" data-toggle="modal" ng-click="beginEdit(task)">Edit</a>
</td>
</tr>
Angularjs code
$scope.beginEdit=function(task){
$scope.title = task.title;
$scope.description=task.description;
$scope.done=task.done;
$scope.uri=task.uri;
$scope.index=$scope.tasks.indexOf(task);
$('#edit').modal('show');
};
$scope.editTask = function() {
title=$scope.title;
description=$scope.description;
done=$scope.done;
uri=$scope.uri;
$('#edit').modal('hide');
var i=$scope.index;
var data={title: title, description: description, done: done };
$http.put(uri, data)
.success(function(){
alert("Success");
});
};

Please check this - : http://plnkr.co/edit/lVkWEsAGVLTY7mGfHP5N?p=preview
Add
$scope.tasks[$scope.index] = data;
In editTask
$scope.editTask = function(obj) {
alert($scope.title);
title = $scope.title;
description = $scope.description;
done = $scope.done;
uri = $scope.uri;
$('#edit').modal('hide');
var i = $scope.index;
var data = {
title: title,
description: description,
done: done
};
alert("uri" + uri);
alert(data.title);
$scope.tasks[$scope.index] = data; // For updating value
$http.put(uri, data)
.success(function() {
//tasks[i].uri(data.uri);
alert("Success");
});
};

Related

Button within modal's table not firing [duplicate]

This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 3 years ago.
Attempted to put a delete button that works in a table into a modal, with a table and it's like the click event is not firing at all. Hit's not back end code, no console.log(s), or js break points. Am I missing something?
Modal's Table
<table class="table table-hover table-md ">
<thead>
<tr>
<td class="text-left TableHead">Role</td>
<td class="text-right TableHead">Delete</td>
</tr>
</thead>
#*--Table Body For Each to pull DB records--*#
<tbody>
#foreach (var role in Model.Roles)
{
<tr>
<td>#role</td>
<td>
<button class="sqButton btnRed float-right zIndex"
title="Delete" data-toggle="ajax-modal" data-target="#deleteRoleUser"
data-url="#Url.Action("Delete", "Administration",
new {Id = Model.Id , Type = "roleUser"})" >
<i class="glyphicon glyphicon-remove"></i>
</button>
</td>
</tr>
}
</tbody>
</table>
Controller that it's supposed to call
[HttpGet]
public async Task<IActionResult> Delete(string id, string type)
{
if (type == "user") {
ViewBag.Type = "user";
var user = await userManager.FindByIdAsync(id);
if (user == null)
{
ViewBag.ErrorMessage = $"User with Id = {id} cannot be found";
return View("NotFound");
}
var model = new EditUserViewModel
{
Id = user.Id,
UserName = user.UserName,
};
ViewBag.UN = user.UserName;
return PartialView("~/Views/Modals/_DeleteModalPartial.cshtml", model);
}
if (type == "roleUser")
{
ViewBag.Type = "roleUser";
var role = await roleManager.FindByIdAsync(id);
if (role == null)
{
ViewBag.ErrorMessage = $"Role with Id = {id} cannot be found";
return View("NotFound");
}
var model = new EditRoleViewModel
{
Id = role.Id,
RoleName = role.Name,
};
ViewBag.Role = role.Name;
return PartialView("~/Views/Modals/_DeleteModalPartial.cshtml", model);
}
else
{
ViewBag.ErrorMessage = $"cannot be found";
return View("NotFound");
}
}
I am not sure why the click event on the button is not working at all. I have tried removing random code and literally nothing is making it go over to the controller at the least.
EDIT added javascript
$(function () {
var placeholderElement = $('#modal-placeholder');
$('[data-toggle="ajax-modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
});
$('.sqButton').click( function (event) {
event.stopPropagation();
});
Since the button doesn't exist on page load you will have to create a event delegate to something that does exist on page load that will attach the event to the right element when it finally does appear in the DOM
In this case we will use the document (because it always exists on page load, some people use 'body') to delegate the event to the [data-toggle="ajax-modal"], like this:
$(document).on('click', '[data-toggle="ajax-modal"]', function (event) {
// code here
});
This will attach the event to the [data-toggle="ajax-modal"] elements on page load AND after page load if the element gets added later.
Try replacing your javascript code
$('.sqButton').click( function (event) {
event.stopPropagation();
});
With the following code
$('.sqButton').click(function(event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
placeholderElement.html(data);
placeholderElement.find('.modal').modal('show');
});
});
if you manually force click, does it hit your controller?
document.querySelector('.btnRed').click();
is there any other element(s) "hijacking" click event?

DropDownList Change() doesn't seem to fire

So, I have been bashing my head against the desk for a day now. I know this may be a simple question, but the answer is eluding me. Help?
I have a DropDownList on a modal that is built from a partial view. I need to handle the .Change() on the DropDownList, pass the selected text from the DropDownList to a method in the controller that will then give me data to use in a ListBox. Below are the code snippets that my research led me to.
all other controls on the modal function perfectly.
Can anyone see where I am going wrong or maybe point me in the right direction?
ProcessController
// I have tried with [HttpGet], [HttpPost], and no attribute
public ActionResult RegionFilter(string regionName)
{
// Breakpoint here is never hit
var data = new List<object>();
var result = new JsonResult();
var vm = new PropertyModel();
vm.getProperties();
var propFilter = (from p in vm.Properties
where p.Region == regionName && p.Class == "Comparable"
select p).ToList();
var listItems = propFilter.ToDictionary(prop => prop.Id, prop => prop.Name);
data.Add(listItems);
result.Data = data;
return result;
}
Razor View
#section scripts{
#Scripts.Render("~/Scripts/ui_PropertyList.js")
}
...
<div id="wrapper1">
#using (Html.BeginForm())
{
...
<div id="fancyboxproperties" class="content">
#Html.Partial("PropertyList", Model)
</div>
...
<input type="submit" name="bt_Submit" value="#ViewBag.Title" class="button" />
}
</div>
Razor (Partial View "PropertyList.cshtml")
...
#{ var regions = (from r in Model.Properties
select r.Region).Distinct(); }
<div>
<label>Region Filter: </label>
<select id="ddl_Region" name="ddl_Region">
#foreach (var region in regions)
{
<option value=#region>#region</option>
}
</select>
</div>
// ListBox that needs to update after region is selected
<div>
#Html.ListBoxFor(x => x.Properties, Model.Properties.Where(p => p.Class == "Comparable")
.Select(p => new SelectListItem { Text = p.Name, Value = p.Id }),
new { Multiple = "multiple", Id = "lb_C" })
</div>
...
JavaScript (ui_PropertyList.js)
$(function () {
// other events that work perfectly
...
$("#ddl_Region").change(function () {
$.getJSON("/Process/RegionFilter/" + $("#ddl_Region > option:selected").attr("text"), updateProperties(data));
});
});
function updateProperties(data, status) {
$("#lb_C").html("");
for (var d in data) {
var addOption = new Option(data[d].Value, data[d].Name);
addOption.appendTo("#lb_C");
}
}
The callback function passed to your $.getJSON method is wrong. You need to pass a reference to the function, not to invoke it.
Try this:
$.getJSON("/Process/RegionFilter/" + $("#ddl_Region > option:selected").text(), updateProperties);
Also, in order to get the text of the selected drop-down option, you need to use the text() function:
$("#ddl_Region > option:selected").text()
See Documentation

Infinite scrolling fills completely rather than incrementally

I am attempting to create infinite scrolling on my web page using an example I found. However, the page fills up completely with all the items instead of just showing several items at a time. In other words it is not doing infinite scrolling. I noticed in some of the examples they parsed out data in chunks but in the real world how are you supposed to do that?
Below is my html code:
<table class="table table-striped table-bordered"><tr>
<th style="text-align:center;">User ID</th> <th>Username</th><th>Rank</th>
<th>Posts</th><th>Likes</th> <th>Comments</th> <th>Flags</th><th>Status</th><th>Action</th></tr>
<tr><td class="center">
<div ng-app='scroll' ng-controller='Scroller'>
<div when-scrolled="loadMore("")">
<div ng-repeat='item in items'>
<span>{{item.id}}
<span style="position:absolute;left:140px;">{{item.username}}</span>
<span style="position:absolute;left:290px;">{{item.rank}}</span>
<span style="position:absolute;left:360px;">{{item.posts}}</span>
<span style="position:absolute;left:440px;">{{item.likes}}</span>
<span style="position:absolute;left:530px;">{{item.comments}}</span>
<span style="position:absolute;left:640px;">{{item.flags}}</span>
<span class="label label-success" style="position:absolute;left:710px;">Active</span>
<a style="position:absolute;left:790px;" class="btn btn-info" style="width:30px" ng-href='/admin/userDetail?userid={{item.id}}'>
View Detail</a>
<hr>
</div>
</div>
</div>
</td></tr>
</table>
Below is my angularjs code:
function Scroller($scope, $http, $q, $timeout) {
$scope.items = [];
var lastuser = '999999';
$scope.loadMore = function(type) {
todate = document.getElementById("charttype").value;
var url = "/admin/getusers?type=" + todate + "&lastuser=" + lastuser;
var d = $q.defer();
$http({
'url': url,
'method': 'GET'
})
.success(function (data) {
var items = data.response;
for (var i = $scope.items.length; i < items.length; i++) {
$scope.items.push(items[i]);
count++;
if (count > 100)
{
lastuser = $scope.items[i].id;
break;
}
d.resolve($scope.items);
d.promise.then(function(data) {
});
}
)
.error(function (data) {
console.log(data);
});
return d.promise;
};
$scope.loadMore();
}
angular.module('scroll', []).directive('whenScrolled', function() {
return function(scope, elm, attr) {
var raw = elm[0];
alert("scroll");
elm.bind('scroll', function() {
if (raw.scrollTop + raw.offsetHeight >= raw.scrollHeight) {
scope.$apply(attr.whenScrolled);
}
});
};
});
My question is why does my web page show all 3200 lines initially rather than allowing me to do infinite scrolling. You will notice I put an alert in the scroll module and it is never displayed. Do I have to incrementally read my database? Any help is appreciated.
You are adding all of the items returned from your API call into $scope.items.
for (var i = 0; i < items.length; i++) {
$scope.items.push(items[i]);
}
Don't you want to add only a subset of those items?
P.S. Might help if you create a Plunkr to show the specific problem.
EDIT:
Based on your comment about the directive not working, I put together this Plunkr, which is a copy of your code but with the $http get code ripped out. The "scroll" alert fires here. I think you're just missing a closing bracket on your for loop (since I don't have your API endpoint to test against, I can't actually run your code live).
EDIT 2:
I'm not sure why you aren't seeing the function fire correctly on scroll. I've set up another plunker where I've changed the result of the scroll event firing to show an alert and load more items from a data variable, so you can see that the scroll event is firing correctly and it will load more items.

Showing an Array using JSON from Database in Ember

Well, I guess I am encountering a bit of an issue again here. I will explain what I am trying to do.
I have a teammembers template in which I want to show Team Members & their specific information from a specific team. For that I have to join 3 tables.
This query should give you an idea:
SELECT *
FROM teams_members tm
inner join members m on tm.members_member_id=m.id
inner join teams t on tm.team_team_id=t.id
WHERE
t.team_name='Vancouver Canuck'
What I initially thought that I can make a simple array and simply do pushObject. But It's not working & and moreover, how would I show them?
Here's what I tried:
App.Model = Ember.Object.extend({});
App.TeammembersController = Ember.ObjectController.extend({
teammembers : [], //This is for getTeamMembers Action, Coming as undefined
selectedTeam : null,
team : function() {
var teams = [];
$.ajax({
type : "GET",
url : "http://pioneerdev.us/users/getTeamNames",
success : function(data) {
for (var i = 0; i < data.teams.length; i++) {
var teamNames = data.teams[i];
teams.pushObject(teamNames);
}
}
});
return teams;
}.property(),
actions : {
getTeamMembers : function() {
teamName = this.get('selectedTeam.team_name');
data = {
team_name : this.get('selectedTeam.team_name'),
};
if (!Ember.isEmpty(teamName)) {
$.ajax({
type : "POST",
url : "http://pioneerdev.us/users/getTeamMembers",
data : data,
dataType : "json",
success : function(data) {
for (var i = 0; i < data.teammembers.length; i++) {
var teamNames = data.teammembers[i].firstname;
teammembers.pushObject(teamNames);
}
}
});
return teammembers;
console.log(teammembers);
} else {
}
}
}
});
I am getting teammember array as undefined in this. The snippet in actions will be responsible for spitting out Team Member's information when Team Name is selected from Ember.Select.
Thanks to https://stackoverflow.com/users/59272/christopher-swasey, I was able to re-use my snippet here:
<script type="text/x-handlebars" id="teammembers">
<div class="row">
<div class="span4">
<h4>Your Team Members</h4>
{{view Ember.Select
contentBinding="team"
optionValuePath="content.team_name"
optionLabelPath="content.team_name"
selectionBinding="selectedTeam"
prompt="Please Select a Team"}}
<button class="btn"
{{action 'getTeamMembers' bubbles=false }}>Get Team Members</button>
</div>
</div>
</script>
Moreover, what will user do, he will select the team from Ember.Select & when he clicks the button, somewhere I should be able to spit out team members & their information. In future, I might want to grab ids and delete them from server as well. How would I do that as well?
So, should I use custom views or is there some other way to do this?
There is an issue with the code that populates properties from ajax. For example the code of property team of App.TeammembersController does the following
1.initializes a local array variable teams
2.uses ajax to retrieve asynchronously the data from server
2.1.meanwhile the teams array within the ajax callback gets populated but never returned at the proper state of including data. It is required to set the controller's property once the teams array has been populated with the data. Then ember's binding will take care of the rest (populate controller's property, notify any other object interested, event the template to render the results)
3.and returns the empty teams array
So, you need to add two lines of code as follows,
team : function() {
var teams = [];
var self = this;/*<- */
$.ajax({
type : "GET",
url : "http://pioneerdev.us/users/getTeamNames",
success : function(data) {
for (var i = 0; i < data.teams.length; i++) {
var teamNames = data.teams[i];
teams.pushObject(teamNames);
}
self.set("team",teams);/*<- */
}
});
return teams;
}.property()
The same should happen for the other properties you retrieve from ajax.
EDIT1
Below is an example based on your code. The code has been moved inside the IndexController and the button doing some action has been disabled for simplicity.
http://emberjs.jsbin.com/IbuHAgUB/1/edit
HBS
<script type="text/x-handlebars" data-template-name="index">
<div class="row">
<div class="span4">
<h4>Your Team Members</h4>
{{view Ember.Select
content=teams
optionValuePath="content.team_name"
optionLabelPath="content.team_name"
selection=selectedTeam
prompt="Please Select a Team"}}
<button class="btn"
{{action 'getTeamMembers' bubbles=false }} disabled>Get Team Members</button>
</div>
</div>
selected team:{{selectedTeam.team_name}}
</script>
JS
App = Ember.Application.create();
App.Router.map(function() {
// put your routes here
});
App.Model = Ember.Object.extend({});
App.IndexController = Ember.ObjectController.extend({
test:"lalal",
teammembers : [],
selectedTeam : null,
teams : function() {
//var teams = [];
var self = this;
/*$.ajax({
type : "GET",
url : "http://pioneerdev.us/users/getTeamNames",
success : function(data) {
for (var i = 0; i < data.teams.length; i++) {
var teamNames = data.teams[i];
teams.pushObject(teamNames);
}
}
});*/
setTimeout(function(){
var data = [{team_name:'team1'}, {team_name:'team2'}, {team_name:'team3'}];//this will come from the server with an ajax call i.e. $.ajax({...})
self.set("teams",data);
},1000);//mimic ajax call
return [];
}.property(),
actions : {
getTeamMembers : function() {
teamName = this.get('selectedTeam.team_name');
data = {
team_name : this.get('selectedTeam.team_name')
};
if (!Ember.isEmpty(teamName)) {
/*$.ajax({
type : "POST",
url : "http://pioneerdev.us/users/getTeamMembers",
data : data,
dataType : "json",
success : function(data) {
for (var i = 0; i < data.teammembers.length; i++) {
var teamNames = data.teammembers[i].firstname;
teammembers.pushObject(teamNames);
}
}
});*/
return teammembers;
} else {
}
}
}
});
The same concept can be followed to retrieve any data from the server and modify/delete it as well. Just have in mind that all requests are async and within the callback functions you should update your ember app model/data, then ember bindings do all the magic.
EDIT2
In order to show the team members in a separate view (based on last comments) once the team is selected, either by clicking the button or from another bound property you may request via ajax the members for the selected team id (unless you have already loaded them eagerly) you can render the property of teammembersinside an included view or partial. For instance the same example and when the button is pressed members appear (without logic hardcoded but async lazy loaded data),
http://emberjs.jsbin.com/IbuHAgUB/2/edit
HBS
<script type="text/x-handlebars" data-template-name="_members">
<i>this is a partial for members</i>
{{#each member in teammembers}}<br/>
{{member.firstName}}
{{/each}}
</script>
JS
App.IndexController = Ember.ObjectController.extend({
test:"lalal",
teammembers : [],
selectedTeam : null,
teams : function() {
var self = this;
setTimeout(function(){
var data = [{team_name:'team1'}, {team_name:'team2'}, {team_name:'team3'}];//this will come from the server with an ajax call i.e. $.ajax({...})
self.set("teams",data);
},1000);//mimic ajax call
return [];
}.property(),
actions : {
getTeamMembers : function() {
var self = this;
setTimeout(function(){
var data = [{firstName:'member1'}, {firstName:'member2'}];//this will come from the server with an ajax call i.e. $.ajax({...})
self.set("teammembers",data);
},1000);//mimic ajax call
}
}
});

Show/hide a button inside ng-repeat

I am trying to show/hide buttons on a ng-repeat (a simple table). A delete button replaced by a conform button.
Here is my code
..... Angular stuff .....
function ContactsCtrl($scope, $http) {
$scope.order = '-id';
$scope.currentPage = 0;
$scope.pageSize = 15;
$http.get('/events/<%= #event.id -%>/contacts.json').success(function(data) {
$scope.contacts = data;
$scope.numberOfPages=function(){
return Math.ceil($scope.contacts.length/$scope.pageSize);
}
});
$scope.clickDelete = function(e,t) {
console.log("delete");
// rest api stuff...
$scope.contacts.splice(e, 1); // This WORKS!
};
$scope.showDelete = function(e,t) {
e.showDeleteButton = true; // This DOES NOT
};
}
And in HTML:
<tr ng-repeat="contact in contacts | filter:search | orderBy:order | startFrom:currentPage*pageSize | limitTo:pageSize">
<td>{{contact.email}}</td>
...
<td>delete
confirm
</td>
</tr>
You don't appear to be returning a value from the showDelete function. It also looks like there is a property on the JSON object 'showDeleteButton' which you could bind to directly.
Example plnkr: http://plnkr.co/edit/eZTFyw9tGeWEfYw0U0I8
It seems like what you are trying to do is have the delete button just set a flag that will show the confirm button which will actually perform the delete, correct? ng-repeat creates a new child scope for each element, so you could just set a 'confirmable' flag on the child scope and use that (fiddle):
<a ng-click="confirmable = true">delete</a>
<a ng-show="confirmable" ng-click="clickDelete(contact)">confirm</a>
<a ng-show="confirmable" ng-click="confirmable = false">cancel</a>
Also it looks like you're passing the contact object to your clickDelete function and using it as an index into the array so I don't know why that works. The fiddle uses indexOf to find the index to delete.
This is how I did it:
JavaScript:
$scope.clickDelete = function(contact,i) {/* ... */ $scope.contacts.splice(i, 1);};
$scope.clickShowConfirm = function(contact) {contact.showdelete = true;};
$scope.clickCancel = function(contact) {contact.showdelete = false;}
$scope.showOrHide = function(contact) {return contact.showdelete;};
HTML:
delete
ok
cancel

Categories