ng-Click does not works in ng-repeat table - javascript

I have aproblem with angularjs ng-click does not works, my model is not updated.
When I want to read the model variables are empty.
I'm using bootstrap popup to show the model values(title, action is using for validation in a funciton inside controller).
HTML code
<button ng-click="title = 'Add Project'; action='Add'" data-toggle="modal" data-target="#myModal" id="btnOpenPopUpForAdding" class="btn btn-default" title="Add new project"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span></button>
<table class="table" id="tblProjects" style="display:none;">
<thead>
<tr>
<th>
</th>
<th>
Project Name
</th>
<th>
Project Description
</th>
</tr>
</thead>
<tr ng-repeat="project in projects" >
<td>
<button ng-click="title = 'Update Project'; action='Update'" data-toggle="modal" data-target="#myModal" class="btn btn-default" title="Update project">
<span class="glyphicon glyphicon-edit" aria-hidden="true"></span>
</button>
</td>
<td>
<span>{{project.ProjectName}}</span>
</td>
<td>
<span>{{project.ProjectDescription}}</span>
</td>
</tr>
</table>
#Html.Partial("../ProjectView")
</div>
Partial view
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">{{title}}</h4>
</div>
<div class="modal-body">
<label for="txtProjectName">Project Name</label>
<input ng-model="singleProject.ProjectName" type="text" class="form-control" style="width:65%" id="txtProjectName" placeholder="Type the project name" />
<br />
<label for="txtProjectDescription">Project Description</label>
<textarea ng-model="singleProject.ProjectDescription" class="form-control" style="width:65%" id="txtProjectDescription" placeholder="Type the project description" rows="4"></textarea>
</div>
<div class="modal-footer">
<button id="btnSave" type="button" class="btn btn-primary" ng-click="ThrowEvent()">Save</button>
<button id="btnCancel" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
</div>
Controller code
$scope.ThrowEvent = function () {
if ($scope.action == 'Add')
$scope.AddProject($scope.singleProject);
if($scope.action == 'Update')
$scope.UpdateProject($scope.singleProject);
//if($scope.action == 'Delete')
}

The issue is that ng-repeat creates separate child scopes. In your case ng-click="title = 'Update Project'; action='Update'" where title and action are assigned to the child scope, not the parent.
To fix this you must prefix your model in your controller, for example
$scope.myActions = {title: 'Default Title', action: 'Default action'};
Then you can change ng-click="title = 'Update Project'; action='Update'" to ng-click="myActions.title = 'Update Project'; myActions.action='Update'"

ng-repeat will create a new scope for each iteration.
"title = 'Update Project'; action='Update'" will execute successful, but it will write the values to the sub-scope of ng-repeat and is not visible by the controller.
To solve the issue you can create a data container in the controller
$scope.data = {};
and write to the container
ng-click="data.title = 'Update Project'; data.action='Update'"`

Related

How to launch bootstrap modal to launch on same page to save?

When I click on the button to launch my modal, it rather duplicataes the content on the same browser page and this is the "Js error" i get in my console window. Tried many suggestions but still.Please help.
Uncaught TypeError: Cannot read properties of undefined (reading 'classList')
at Pe._isAnimated (modal.js:312:26)
at Pe._initializeBackDrop (modal.js:194:24)
at new Pe (modal.js:82:27)
at Pe.getOrCreateInstance (base-component.js:55:41)
at HTMLButtonElement.<anonymous> (modal.js:414:22)
at HTMLDocument.n (event-handler.js:120:21)
My Code:
Controller:
using BOGBitwiseApp.Data;
using BOGBitwiseApp.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Dynamic;
namespace BOGBitwiseApp.Controllers
{
public class CustomerRequestController : Controller
{
private readonly ApplicationDbContext _context;
public CustomerRequestController(ApplicationDbContext context)
{
_context = context;
}
//Get: Customer Requests
public IActionResult Index()
{
var customerRequest = _context.CustomerRequests.ToList();
return View(customerRequest);
}
[HttpGet]
public IActionResult Create()
{
CustomerRequestModel customer = new CustomerRequestModel();
return PartialView("AddCustomerModelPartial", customer);
}
Index.cshtml:
#model IEnumerable<BOGBitwiseApp.Models.CustomerRequestModel>
#{
ViewData["Title"] = "Index";
}
<div id="PlaceHolderHere">
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-
target="#addCustomerRequest" data-bs-url="#Url.Action("Create")">New Customer
Request</button>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>
#Html.DisplayNameFor(m => m.AccountName)
</th>
<th>
#Html.DisplayNameFor(m =>m.AccountNumber)
</th>
<th>Action</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model) {
<tr>
<td>
#item.AccountName
</td>
<td>
#item.AccountNumber
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.BitwiseId}) ||
#Html.ActionLink("Delete", "Delete", new { id=item.BitwiseId})
</td>
</tr>
}
</tbody>
PartialView:
I created a partialview "AddCustomerModelPartial.cshtml".
#model CustomerRequestModel
<div class="modal fade" id="addCustomerRequest">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h2 class="modal-title" id="addCustomerRequestLabel">Bitwise
Information</h2>
<button type="button" class="btn-close" aria-label="Close" data-bs-
dismiss="modal">
</button>
</div>
<div class="modal-body">
<form asp-action="Create" >
<div class="form-group">
<label asp-for="AccountName"></label>
<input asp-for="AccountName" class="form-control" />
<span asp-validation-for="AccountName" class="text-danger">
</span>
</div>
<div class="form-group">
<label asp-for="AccountNumber"></label>
<input asp-for="AccountNumber" class="form-control" />
<span asp-validation-for="AccountNumber" class="text-danger">
</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-bs-
dismiss="modal">Cancel Request</button>
<button type="button" class="btn btn-info" data-bs-toggle="modal">Save
Request</button>
</div>
</div>
</div>
</div>
Site.js Code:
This is my js code in the wwwroor folder.
$(function () {
var PlaceHolderElement = $('#PlaceHolderHere');
$('button[data-bs-toggle="modal"]').click(function (event) {
var url = $(this).data('url');
$.get(url).done(function (data) {
PlaceHolderElement.html(data);
PlaceHolderElement.find('.modal').modal('show');
})
})
})
It should be data-url="#Url.Action("Create")" if you want to get the value by using $(this).data('url').
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-
target="#addCustomerRequest" data-url="#Url.Action("Create")">New Customer Request</button>
Another way, if you do not want to change data-bs-url, you can change the js below to receive the url value:
var url = $(this).attr("data-bs-url");

Why isn't my form passing the id to the controller?

I've got an asp.net mvc webpage set up. All of my actions, like: create, edit, etc... have their own views, except delete, because I'm trying to pop up a modal with help from Bootstrap. I pass an id to the modal, through jQuery/JavaScript, and with the asp-action as the form's attribute, it should theoretically work, but well it doesn't.
Index View:
#if (Model.Tenants.Any())
{
<h3>Tenants (#Model.Tenants.Count)</h3>
<div class="table-responsive">
<table class="table table-striped table-sm">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Id</th>
<th>UrlFriendlyName</th>
<th>MicrosoftGraphTenantId</th>
<th></th>
</tr>
</thead>
<tbody>
#foreach (var tenant in Model.Tenants.OrderByDescending(x => x.Name))
{
<tr>
<td>
<button class="btn btn-primary" onclick="document.location.href = '#Url.Action("Index", "User", new {id = tenant.Id})'">Show Users</button>
</td>
<td>
#tenant.Name
</td>
<td>
#tenant.Id
</td>
<td>
#tenant.UrlFriendlyName
</td>
<td>
#tenant.MicrosoftGraphTenantId
</td>
<td>
<div class="btn-group-justified pull-right ">
<button class="btn btn-success" onclick="document.location.href = '#Url.Action("Edit", "Tenant", new {id = tenant.Id})'">Edit</button>
<button type="button" class="btn btn-danger" onclick="deleteTenant('#tenant.Id', '#tenant.Name')" data-toggle="modal" data-target="#deleteModal">Delete</button>
</div>
</td>
</tr>
}
</tbody>
</table>
</div>
<div class="align-items-sm-end">
<button onclick="document.location.href='#Url.Action("Create", "Tenant")'" class="btn btn-outline-success">Create new Tenant</button>
</div>
<div class="modal fade" id="deleteModal" data-backdrop="static" data-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Are you sure you want to delete the selected Tenant?</p>
</div>
<div class="modal-footer">
<form asp-action="Delete">
<input type="hidden" id="tenantidinput"/>
<button type="submit" class="btn btn-outline-danger">Delete Tenant</button>
</form>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</div>
</div>
</div>
</div>
}
Delete Action in Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> DeleteAsync(Guid id)
{
if (ModelState.IsValid && id != Guid.Empty)
{
var tenant = await _context.Tenants.AsQueryable().Where(x => x.Id == id).FirstOrDefaultAsync().ConfigureAwait(false);
_context.Tenants.Remove(tenant);
await _context.SaveChangesAsync().ConfigureAwait(false);
}
return RedirectToAction("Index");
}
Javascript:
function deleteTenant(tenantid, tenantname) {
$(".modal-title").text("Delete " + tenantname);
$("#tenantidinput").attr("name", ''+tenantid+'');
}
Input getting the id as the value of the name:
When debugging, it receives no id whatsoever:
The javascript-function receives the parameters just fine. I think that the problem lies in, the way, the form passes the id to the controller. It somehow doesn't pass the value of the name-attribute.
This is happening for two reasons. Firstly, the hidden input should have the name matching the argument in the action. In your case id:
<input type="hidden" name="id" id="tenantidinput" />
Secondly, your JS should set the value of the field, not its name:
function deleteTenant(tenantid, tenantname) {
$(".modal-title").text("Delete " + tenantname);
$("#tenantidinput").val(tenantid);
}

how to submit a non-form element using angular2

<tbody>
<tr *ngFor="let gasType of staffConfig.gasTypes">
<td class="col-md-3">
<input class="gas-name form-control" type="text" [(ngModel)]="gasType.name" name="gasName"
[disabled]="!isStaffEnabled">
</td>
</tr>
</tbody>
</table>
</div>
<div class="panel panel-default">
<!-- Default panel contents -->
<div class="panel-heading">
<h3 class="panel-title">
<img src="/assets/brand-icon.png">
<span>Brands</span>
</h3>
</div>
<!-- Table -->
<table class="table">
<tbody>
<tr *ngFor="let brand of staffConfig.brands;let i = index;">
<td>
<input class="form-control" type="text" [(ngModel)]="brand.name" name="brands"
[disabled]="!isStaffEnabled">
</td>
</tr>
</tbody>
</table>
</div>
</tab>
<button id="saveChangesBtn" type="button" class="btn btn-primary" disabled>Save Changes</button>
I want to bind the "save" button to a method in the component. So I changed:
<button id="saveChangesBtn" type="button" (ngSubmit)="registerUser(registrationForm.value) class="btn btn-primary" disabled>Save Changes</button>
but then, if that's not a <form> how do I bind the fields to a model?
In other words how can I send these fields to the server?
I have to read them from the component and then assemble an object.
But how can I access the non-form model like registrationForm.value?
If you are using ngModel outside of the <form> you must specify [ngModelOptions]={standalone:true}.
Template
<div class="not-a-form">
<input type="text" [(ngModel)]="model.foo" [ngModelOptions]="{standalone: true}" />
<input type="text" [(ngModel)]="model.bar" [ngModelOptions]="{standalone: true}" />
<button type="button" (click)="save(model)"> Send </button>
</div>
Component
#Component({
selector: 'selector',
...
})
class SomeComponent {
model: any = {};
save(data) {
console.log(data);
}
}

JS Modal not displaying variables in input fields - server config requirements?

after spending a fair amount of time researching and debugging the issues, I am finally at my wits' end and would appreciate some help:
Problem:
Modal does not display variables insert into its INPUT fields.
Background info:
I am pulling records from a MySQL table which is displayed line by line, with an "EDIT" button placed in the last column of each row. The EDIT button is supposed to launch a modal populated with the records data in each INPUT field, allowing the user to edit the record.
What I've tried so far:
checked whether the generated variables are empty by looking at what's printed in the source. All variables are generated correctly and have indeed values printed.
I copied the #MyModal JS and <div> from the official documentation but cannot get it work either (Link)
copied the #EDIT modal from another thread on the web which worked for another user
included references from Google and MaxCDN instead of my own local copies of JS Bootstrap / jQuery / CSS
tried to run the code on my XAMPP server without success, showing the some symptoms
opened the website in IE / Chrome / Firefox / Safari (MAC), all with the same result
ran a JS Fiddle successfully handing over the variables which makes me think that there might be a server issue / configuration requirement that I am not aware of (LINK)
The code:
<html>
<head>
<!-- include jQuery 3.1.0 + jQuery CSS + min JavaScript -->
<!-- latest jQuery 3.1.0 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<!-- JavaScript for Modal, #MyModal is straight from the documentation, #edit is a solution I got off the web -->
<script>
$('#edit').on('show.bs.modal', function(e) {
var dataID = $(e.relatedTarget).data('id');
$(e.currentTarget).find('input[name="dataID"]').val(dataID);
var dataDate = $(e.relatedTarget).data('date');
$(e.currentTarget).find('input[name="dataDate"]').val(dataDate);
});
$('#myModal').on('show.bs.modal', function(e) {
var dataID = $(e.relatedTarget).data('id');
$(e.currentTarget).find('input[name="dataID"]').val(dataID);
var dataDate = $(e.relatedTarget).data('date');
$(e.currentTarget).find('input[name="dataDate"]').val(dataDate);
var dataTime = $(e.relatedTarget).data('time');
$(e.currentTarget).find('input[name="dataTime"]').val(dataTime);
var dataStaff = $(e.relatedTarget).data('staff');
$(e.currentTarget).find('input[name="dataStaff"]').val(dataStaff);
var dataDept = $(e.relatedTarget).data('dept');
$(e.currentTarget).find('input[name="dataDept"]').val(dataDept);
var dataProb = $(e.relatedTarget).data('prob');
$(e.currentTarget).find('input[name="dataProb"]').val(dataProb);
var dataGuest = $(e.relatedTarget).data('guest');
$(e.currentTarget).find('input[name="dataGuest"]').val(dataGuest);
var dataRoom = $(e.relatedTarget).data('room');
$(e.currentTarget).find('input[name="dataRoom"]').val(dataRoom);
});
</script>
<!-- End of Modal Javascript -->
</head>
<body>
<table>
<tr>
<td>
<label>Button for Modal #MYMODAL"</label>
</td>
<td>
<button type="button" class="btn btn-block btn-primary btn-xs" data-toggle="modal" data-target="#myModal" data-keyboard="true"
data-id="1234"
data-date="2001-01-31"
data-time="13:00"
data-staff="Some Name"
data-dept="Some Department"
data-prob="Problem"
data-guest="Guest Name"
data-room="1111" >Modal 1</button>
</td>
</tr>
<tr>
<td>
<label>Button for Modal #EDIT"</label>
</td>
<td>
<button type="button" class="btn btn-block btn-primary btn-xs" data-toggle="modal" data-target="#edit" data-keyboard="true"
data-id="1234"
data-date="2001-01-31">Modal 2</button>
</td>
</tr>
</table>
<!-- Modal MYMODAL -->
<div class="modal modal-primary modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Edit Record</h4>
</div>
<div class="modal-body">
<table class="table">
<tr>
<td>ID No.: </td>
<td>
<input type="text" id="dataID" name="dataID" value="" disabled />
</td>
</tr>
<tr>
<td>Date: </td>
<td>
<input type="date" id="dataDate" name="dataDate" value="" />
</td>
</tr>
<tr>
<td>Time: </td>
<td>
<input type="time" id="dataTime" name="dataTime" value="" />
</td>
</tr>
<tr>
<td>Staff: </td>
<td>
<input type="text" name="dataStaff" value="" />
</td>
</tr>
<tr>
<td>Department: </td>
<td>
<input type="text" name="dataDept" value="" />
</td>
</tr>
<tr>
<td>Problem: </td>
<td>
<input type="text" name="dataProb" value="" />
</td>
</tr>
<tr>
<td>Guest: </td>
<td>
<input type="text" name="dataGuest" value="" />
</td>
</tr>
<tr>
<td>Room No.: </td>
<td>
<input type="text" name="dataRoom" value="" />
</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary">Save changes</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- /.Modal MYMODAL -->
<!-- Modal EDIT-->
<div class="modal fade" id="edit" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Edit Details</h4>
</div>
<div class="modal-body">
<table class="table">
<tr>
<td>ID No.: </td>
<td>
<input type="text" id="dataID" name="dataID" value="" disabled />
</td>
</tr>
<tr>
<td>Date: </td>
<td>
<input type="date" id="dataDate" name="dataDate" value="" />
</td>
</tr>
</table>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<!-- /.Modal EDIT -->
</body>
</html>
Your script needs to be at the bottom, after the html. I believe that when your script is executing, the html does not yet exist.

Populate dropdown value inside ng-repeat

I am facing an issue with my Angular code, while populating the dropdown inside a HTML table (Code given below).
Could you please help me with what should be done inside modify() to populate the dropdown ?
HTML Code:
<table class="table" ng-app="empApp" ng-controller="employeeController">
<thead>
<tr class="info">
<th>Emp Name</th>
<th>Status</th>
<th colspan="2"> </th>
</tr>
</thead>
<tbody>
<tr ng-repeat="emp in employees">
<td>
<div ng-hide="editingData[emp.id]">{{ emp.name }}</div>
<div ng-show="editingData[emp.id]"><input type="text" ng-model="emp.name" /></div>
</div>
</td>
<td>
<div ng-hide="editingData[emp.id]">{{ emp.status.name }}</div>
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status"
ng-options="status.id as status.name for status in statuses"></select>
</td>
<td colspan="2">
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[employee.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[employee.id]" ng-click="update(emp)">Update</button>
</div>
</td>
</tr>
</tbody>
</table>
Javascript Code:
var empApp = angular.module("empApp", []);
empApp.controller('employeeController', function($scope, $http) {
$scope.statuses = [{"id":1,"name":"Active"}, {"id":1,"name":"Inactive"}];
$scope.employees = [{"id":1,"name":"Mark","status":{"id":1,"name":"Active"}},{"id":2,"name":"Sara","status":{"id":2,"name":"Inactive"}}];
$scope.editingData = {};
for (var i = 0, length = $scope.employees.length; i < length; i++) {
$scope.editingData[$scope.employees[i].id] = false;
}
$scope.modify = function(employee){
$scope.editingData[employee.id] = true;
//Set Employee Status correctly here to populate the dropdown
};
});
My problem is I am NOT able to populate the dropdown with the existing value, as show in the diagram below:
I made this plunker, check if it's what you need.
1: Both status are with id 1. Change them
From:
$scope.statuses = [{"id":1,"name":"Active"}, {"id":1,"name":"Inactive"}];
To:
$scope.statuses = [{"id":1,"name":"Active"}, {"id":2,"name":"Inactive"}];
2:Change your select ng-model to emp.status.id.
From:
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status"
ng-options="status.id as status.name for status in statuses"></select>
To:
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status.id"
ng-options="status.id as status.name for status in statuses"></select>
3: Change your buttons ng-hide/ng-show
From:
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[employee.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[employee.id]" ng-click="update(emp)">Update</button>
</div>
To:
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[emp.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[emp.id]" ng-click="update(emp)">Update</button>
</div>
Update:
As #Rajesh said below you can store the status_id instead of entire status object. Check his fiddle.
Just replace your select tag part with this code
<select ng-show="editingData[emp.id]" class="form-control" ng-model="emp.status"
ng-options="status as status.name for status in statuses track by status.id"></select>
This is because in ng-model you are passing the full object and you need the full object to be tracked by ID in order to fill the dropdown and relevant dropdown value to be selected
Also in your buttons:
<div class="btn-group">
<button type="submit" class="btn btn-primary" ng-hide="editingData[emp.id]" ng-click="modify(emp)">Modify</button>
<button type="submit" class="btn btn-primary" ng-show="editingData[emp.id]" ng-click="update(emp)">Update</button>
</div>
Because you are referencing it by 'emp' and not 'employee' inside ng-repeat as it will be dynamic
You are looping through
<tr ng-repeat="emp in employees">
But in the select list, you are toggling based on:
editingData[employee.id]
Try changing that to
editingData[emp.id]
use emp.id in your button and also in your modify function and loop
use $scope.employees[i].isVisible = false and ng-hide = $scope.employees.isVisible ng-show = $scope.employees.isVisible

Categories

Resources