i have a view in which i want to show textbox and button to save and edit the database table if in the table id comment is null i want to show textbox to enter the comment and if comment is there in the table then show the comment, but when user clicks the second(edit) button i want that textbox and button should reappear in that place, i put an if condition to check if my table column is null then show textbox and button to enter data into that column and i have second button to get back the textbox and buttons with the comment text.
My code is here
#if (item.Comments == null)
{
<div class="form-inline comments">
<textarea class="form-control commentText" placeholder="Enter Your Comment"></textarea>
<button type="submit" data-cid="#item.RoomId" class="btn btn-primary save"><i class="fas fa-save h3"></i></button>
<button type="submit" data-eid="#item.RoomId" class="btn btn-secondary edit"><i class="fas fa-edit h3"></i></button>
</div>
}
else
{
<div class="commentText">
#Html.DisplayFor(modelItem => item.Comments)
</div>
}
$('.save').click(function () {
var cmt = $('.commentText').val();
$.post("#Url.Action("AddComment", "ReceptionHk")", { id: $(this).data("id"), newComment: cmt });
});
$('.edit').click(function () {
$('.comments').show();
$('.commentText').hide();
});
My Controller Method
public void AddComment(int id, string newComment)
{
var roomcmt = db.SingleOrDefault<Room>(id);
if (ModelState.IsValid)
{
roomcmt.Comments = newComment;
var r = db.Update(roomcmt);
}
}
How to show the textbox and two button again when edit button is clicked
Please help me with this
Change your code in the following way:
A: Remove the line #if (item.Comments == null) and make the view display the creation section by default.
B: For creating/editing the comments have your code something like this:
<div class="form-inline comments">
<textarea class="form-control commentText" placeholder="Enter Your Comment"></textarea>
<button type="submit" data-cid="#item.RoomId" class="btn btn-primary save"><i class="fas fa-save h3"></i></button>
</div>
C: And then add a scope validation on the list as:
#if(item.Comments!=null)
{
<display your list here>
}
For displaying the comments, instead of statically displaying the comments use a table and do a foreach loop on the comments in the table to create rows with 2 columns in it as Comment,Edit.
Ex:
<table>
#foreach(var comment in item.Comments)
{
<tr>
<td>#comment.Text</td>
<td><button data-id="#comment.RoomId">Edit</button></td>
</tr>
}
</table>
and on the click of the Edit button call a javascript function that will call the retrieval of that comment and populate your editing fields after which you can later use it to update.
Your view will look something like this:
<div class="form-inline comments">
<textarea class="form-control commentText" placeholder="Enter Your Comment"></textarea>
<button type="submit" data-cid="#item.RoomId" class="btn btn-primary save"><i class="fas fa-save h3"></i></button>
</div>
#if(item.Comments!=null)
{
<table>
#foreach(var comment in item.Comments)
{
<tr>
<td>#comment.Text</td>
<td><button data-id="#comment.RoomId">Edit</button></td>
</tr>
}
</table>
}
Rest: implement your JS function to retrieve and create the comments.
Related
I have a table that is generated from server side on a partial and rendered using ajax. Because of this I lose binding.
So my only option is to map everything to a JavaScript array and post it.
Is there a way to map everything using jQuery without having to iterate every row then every column and look for each input one by one?
Are there any other options? Perhaps I have to use something like Vue?
Here is my partial:
#model Project.Areas.Robotics.Models.ViewModels.DefectRecordViewModel
<form method="post">
<card>
<card-header icon="fas fa-thumbs-down" title="Peças NOK">
</card-header>
<card-body>
<div class="form-row">
<div class="form-group col-md-6">
<h4>
<span class="">
<b><i class=""></i>Registo</b> #Model.ProductionRecordId
</span>
</h4>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-6">
<label asp-for="References"></label>
<select id="references-nok" asp-items="Model.References" class="custom-select custom-select-sm" onchange="selectReferences(this)">
<option value="">--</option>
</select>
</div>
</div>
<div class="table-responsive">
<table id="tblDefects" class="table table-sm" style="width:100%;">
<thead class="bg-olive">
<tr>
<th>#Html.DisplayNameFor(model => model.DefectCodes[0].DefectCodeId)</th>
<th>#Html.DisplayNameFor(model => model.DefectCodes[0].Quantidade)</th>
<th>#Html.DisplayNameFor(model => model.DefectCodes[0].Detalhes)</th>
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.DefectCodes.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(model => model.DefectCodes[i].DefectCode)
<input type="hidden" asp-for="DefectCodes[i].DefectCodeId" />
<input type="hidden" class="reference-holder" asp-for="DefectCodes[i].ReferenceId" />
<input type="hidden" asp-for="DefectCodes[i].DefectCodeId" />
</td>
<td>
<input asp-for="DefectCodes[i].Quantidade" class="form-control form-control-sm" />
<span asp-validation-for="DefectCodes[i].Quantidade" class="text-danger"></span>
</td>
<td>
<input asp-for="DefectCodes[i].Detalhes" class="form-control form-control-sm" />
<span asp-validation-for="DefectCodes[i].Detalhes" class="text-danger"></span>
</td>
</tr>
}
</tbody>
</table>
</div>
</card-body>
<card-footer>
<div class="form-row">
<div class="form-group col-md-6">
<button type="button" data-url="#Url.Page("Index","AddDefectCode")" onclick="addDefectRecord(this)" class="btn btn-success btn-sm"><i class="fas fa-plus"></i> Adicionar</button>
<button type="button" onclick="hideDetails()" class="btn btn-danger btn-sm"><i class="fas fa-times"></i> Cancelar</button>
</div>
</div>
</card-footer>
</card>
</form>
I am unable to understand clearly what is Your problem but if You have large number of records and You don't want to load complete at once or want to reload your table without reload or all functionality like paging searching and filter you can use data table plugin
with server side record manipulation if this you are question you can reply this post so i can give you more example or i will give you some example .for your further understanding .
other wise you can elaborate your question with some screen shot so i can understand your roots of problem and give the best possible answers .
Is there a way to map everything using jQuery without having to iterate every row then every column and look for each input one by one?
Since you've configured all the <input/> with well-formed names, you can build a FormData directly.
var formdata = new FormData(someFormElement);
For example, add a submitDefectCode function to send an ajax request as below:
<script>
function submitDefectCode(element){ // the element is the `<button/>` that is clicked
var url = element.getAttribute("data-url");
var form = document.querySelector("form"); // get the `<form>` element
var formdata = new FormData(form);
$.ajax({
method:"post",
url: url,
contentType: false,
processData: false,
data: formdata,
success:function(resp){
console.log(resp); // now you get the response
}
});
}
</script>
And trigger this function when clicking the button:
<button type="button" data-url="#Url.Action("Index","AddDefectCode")"
onclick="event.preventDefault(); submitDefectCode(this);"
class="btn btn-success btn-sm">
<i class="fas fa-plus"></i> Adicionar
</button>
Finally, make your server side code to receive the form data with a [FromForm] attribute:
[HttpPost("/AddDefectCode")] // change this route as you need
public IActionResult TestPost([FromForm]DefectRecordViewModel model)
{
// ... now you get the model automatically
return Json(model);
}
Demo:
Here's a demo screenshot when posting data with multiple table rows:
In case you want to build a javascript array manually, you can use the FormData.entries():
var array= [];
for(var pair of formData.entries()) {
array.push({key: pair[0], value:pair[1]});
}
I used ajax unobtrusive to submit the form on the partial. The model is automatically binded on serverside, no need to do anything manually.
well right now I am doing something like this to find all textbox values which has the same class name.
function generalBottom(anchor) {
var sends = $('input[data-name^="noValues"]').map(function(){
$(this).attr('value',$(this).val());
return $(this).val();
}).get();
}
and i call this function on a onclick of submit button like generalBottom(this)
and I have something like as per my requirement
When I click submit button of User I call a general function passing this as a parameter, but the above code gives me the text values of client as well
["perfect", "hyperjack", "julie", "annoying", "junction", "convulated"], which is undesired, I want only ["annoying", "junction", "convulated"] using my anchor params.
How to do this via my this parameter, I thought to traverse through my tags using children(), parent() but I won't be knowing how many fields user have added as its all dynamic, user can add as many values(text boxes).
I tried this
1) $(anchor).find('.rightAbsNo')
2) $(anchor).find('input[data-name^="noValues"]')
3) $(anchor).find('.rightAbsNo').map(function () {
console.log($(this).find('. showNoButton')); })
None of this worked for me.
My html is somewhat like this, code
<div id="attach0" class="leftbottomno">
<div style="overflow: hidden" class="leftbottomAbsolute" id="">
<form>
<span class="absno"><input type="text" required=""
id="absdelete" data-inputclass="leftbottomAbsoluteNo_class"
value="" class="leftbottomabsolutenotest keys" data-value=""
style="margin-bottom:4px; color: #1c1c1c;"> </span>
<a onclick="addAbsoluteValues(this);" style="margin-left: 50px">
<i class="fa fa-plus-circle color-blue-grey-lighter"></i> </a>
</form>
<a onclick="deleteAbsoluteEmpty(this);> </a><br>
<div class="rightAbsNo" id="yesValueattach">
<div class="rightAbsNoValue">
<input type="text" id="nonattach" placeholder="values"
data-name="noValues" data-inputclass="absYes_class" value="annoying"
class="showNoButton showActivity value" data-value="">
<button type="button" onclick="generalBottom(this);">
<i class="glyphicon glyphicon-ok"></i></button>
</div>
</div>
<div class="rightAbsNo" id="yesValueattach">
<div class="rightAbsNoValue" id=""> <input type="text"
data-name="noValues" data-inputclass="absYes_class" subattribute=""
value="" class="showNoButton showActivity value" data-value="">
<button type="button" onclick="generalBottom(this);">
<i class="glyphicon glyphicon-ok"></i></button>
</div>
</div>
<div class="rightAbsNo" id="yesValueattach">
<div class="rightAbsNoValue" id="">
<input type="text" data-name="noValues"
data-inputclass="absYes_class" placeholder="values" subattribute=""
value="junction" class="showNoButton showActivity value"
data-value="" >
<button type="button" style="display: none;"
onclick="generalBottom(this);">
<i class="glyphicon glyphicon-ok"></i>
</button>
</div>
</div>
</div>
</div>
First of all, you need to define a container to the groups with something like :
<div class="container">input groups</div>
<div class="container">input groups</div>
and change <button type='submit'> to <button type='button'> to prevent submitting the form.
Then change your function to this:
function generalBottom(anchor) {
var all_inputs = $(anchor).parent(".container").find("input");
var input = $(anchor).siblings('input').first();
all_inputs.each(function(){
$(this).val(input.val());
});
}
Here's Jsfiddle
first $(anchor).siblings(input) find inputs
then go through each element from first step and return their value
function generalBottom(anchor) {
var input = 'input[data-name^="noValues"]'
var values = $.map($(anchor).siblings(input), (elemnt, index)=>{
return elemnt.value
})
$('#shows').val(values.join())
}
$('button').on('click',function(){
generalBottom(this)
})
hope this helps
I can display a table of users from my database on my web application using ng-repeat. I can add and delete directly from the web application but now I'm trying to update informations about those users. I would like to click on a button on the row of the user (each rows display informations for one user, 1 row = 1 user) when I clicked on this button I would like to make a form with input fields filled with actual values.
I can only get informations about my users by clicking on this button but I don't know how to "send" informations to this form.
My table of users :
<tr ng-repeat="user in users">
...
</tr>
But something like this is not working at all :
<form>
<label>Name</label>
<input type="text" id="up_name" ng-model="user.name"/>
<label>Age</label>
<input type="text" id="up_age" ng-model="user.age"/>
...
</form>
If you are using this synthax, your form have to be in your ngRepeat. It is not the best way to do it, as you will have a form for user.
I would suggest you something different. In your controller, set an edit() function:
$scope.edit = function(user) {
$scope.editedUser = user;
}
When clicking a user in your table, call the edit() function:
<tr ng-repeat="user in users" ng-click="edit(user)">
...
</tr>
You can now edit in the form the editedUser object:
<form ng-if="editedUser">
<label>Name</label>
<input type="text" id="up_name" ng-model="editedUser.name"/>
<label>Age</label>
<input type="text" id="up_age" ng-model="editedUser.age"/>
...
</form>
What you can do is the following :
<tr ng-repeat="user in users" ng-init="selectedUser = null">
<td> {{ user.name }}</td>... <td ng-click="selectedUser = user"> edit </td>
</tr>
<div ng-if="selectedUser">
<form>
<label>Name</label>
<input type="text" id="up_name" ng-model="user.name"/>
<label>Age</label>
<input type="text" id="up_age" ng-model="user.age"/>
...
</form>
</div>
I think that you are talking about a sort of master-detail ui pattern.
Here it is a public plunker that will solve that kind of problem
Insert the both input and span HTML directive in <td> and use ng-switch : ng-switch-when & ng-switch-default to display only one field.
<td class="sorting_1" ng-switch="mode">
<input type="text" class="form-control small" ng-switch-when="edit" id="edit" ng-model="edit.username">
<span ng-switch-default id="item.username">{{item.username}}</span>
</td>
You need to write a custom directive for it.Reason for writing custom directive is the value of ng-switch will associate with individual instead of global.
In the last <td> tag add : which will contain edit and update buttons:
<td ng-switch="mode">
<button class="btn btn-success btn-xs edit" ng-switch-when="edit" ng-
click="updateItem(edit, index)">
<i class="fa fa-floppy-o"></i>
</button>
<button class="btn btn-success btn-xs" ng-switch-default ng-
click="editItem(item)">
<i class="fa fa-pencil-square-o "></i>
</button>
</td>
JS
$scope.editItem = function(oldData) {
$scope.edit = angular.copy(oldData);
$scope.mode = "edit";
}
$scope.updateItem = function(data, index) {
$scope.$emit('update', data, index);
$scope.mode = "default";
}
The value of input-box will be updated using
$scope.edit = angular.copy(oldData); into editItem() function.
With the use of event emitters modify the main object.
$scope.$on('update', function(event, data, index) {
angular.copy(data, $scope.items[index]);
});
use angular.copy to deep clone value instead of passing value as a reference.
Check http://codepen.io/sumitridhal/pen/YVPQdW
I want to change the label of same button in angularjs according to requirement, same button can be for update and submit.
See the following demo,
Above demo is about the replicate the template. If some template has already data then label of submit button should be Update, other-wise for empty template label should be Submit.
I can't use following logic because it will change all button with same label, but I want to show label Submit only for empty and no-empty to show label Update. How I will do that?
<a class="btn btn-success" ng-click="updateOrder($index)">{{btnText}}</a>
And add some logic to your controller, that will specify text for button:
if (newItem){
$scope.btnText = 'Submit';
}else{
$scope.btnText = 'Update';
}
HTML
<div class="col-md-12" style="bottom:10px" >
<div class="form-group" ng-repeat="field in fields">
<div class="col-md-12">
<div class="col-md-4">
<label class="col-md-12 control-label">Field1</label>
<div class="col-md-12">
<input data-ng-model='field.field1' class="chosen-select input-md form-control sme-input-box"/>
</div>
</div>
<div class="col-md-4">
<label class="col-md-12 control-label">Field2</label>
<div class="col-md-12">
<input ng-model='field.field2' class="chosen-select input-md form-control sme-input-box"/>
</div>
</div>
</div>
<div class="col-md-12">
<div class="col-md-3">
<a class="btn btn-success" ng-click="removeTemplate($index)">Remove</a>
</div>
<div class="col-md-3">
<a class="btn btn-success" ng-click="updateOrder($index)">Submit</a>
</div>
</div>
</div>
<div class="col-md-3" style="top:5px">
<a class="btn btn-success" ng-click="cloneTemplate()">Add</a>
</div>
</div>
Angularjs
$scope.fields=[
{
"field1": "",
"field2": "",
}
]
// update and get invoice details
$scope.cloneTemplate=function(){
var clone_template={ "field1": "", "field2": ""};
$scope.fields.push(clone_template);
}
$scope.removeTemplate= function(templateIndex){
$scope.fields.splice(templateIndex,1);
}
$scope.updateOrder=function(i){
var updateOrder={
"field1":$scope.fields[i].field1,
"field2":$scope.fields[i].field2,
}
alert(updateOrder.field1);
$http.post(config.server, updateOrder)
.success(function(response, status){
console.log(response);
})
.error(function(response, status){
console.log(response);
})
}
I understand that while while adding data you wanted to show Submit button label & show Update button label while updating record.
So as normal practice you are getting this value from the DB, so I'd suggest you to add id column in this object which will be there with fields. Now object will look like {id: 1, field1: '1', field2: 2} so if the element has id that means it has persisted in the database. And obviously if you don't have id in fields record means it has been added from UI.
So the whole logic will look at the id property of your object, if you have id in the record then it will show Update as button label otherwise it would be Submit
<div class="col-md-3">
<a class="btn btn-success" ng-click="updateOrder(field)"
ng-bind="field.id? 'Update': 'Submit'">
Submit
</a>
</div>
So for make your logic working good, you need to get the list again from the database to make your UI consistent.
Working Plunkr
Change your markup for button to show some scope property:
<a class="btn btn-success" ng-click="updateOrder($index)">{{btnText}}</a>
And add some logic to your controller, that will specify text for button:
if (newItem){
$scope.btnText = 'Submit';
}else{
$scope.btnText = 'Update';
}
I'm making a table.
I've made my rows editable with: ng-click="todo.editing = !todo.editing"
index.html
<tr ng-repeat="todo in todos>
<td>
<div ng-hide="todo.editing">{{ todo.id }} </div>
<div ng-show="todo.editing"><input type="id" ng-model="todo.id" /></div>
</td>
<td>
<div ng-hide="todo.editing">{{ todo.text }}</div>
<div ng-show="todo.editing"><input type="text" ng-model="todo.text" /></div>
</td>
</tr>
<button class="btn btn-warning btn-sm ng-scope" ng-click="todo.editing = !todo.editing"><span class="glyphicon glyphicon-pencil"></span></button>
I've made a button to add new rows to the table:
index.html
<button type="button" class="btn btn-default btn-block " ng-click="addRow($storage.todos)">New record</button>
script.js
$scope.addRow = function (arr) {
console.log(arr);
arr.push({'id':$scope.id, 'text': $scope.text});
};
Now I want to expand my addRow() function so I can add a new row and at the same time position myself at that row, and also put me in edit mode.
The problem with position is that I am using pagination. Let's say I am at page one in pagination and the newly row comes at page four. I want to automatically get there.
Can somebody give me a hint? Thanks for your time.
Just make editing property value true during pushing.
Like this
arr.push({'id':$scope.id, 'text': $scope.text,editing:true});
I created a fiddle:
https://jsfiddle.net/0t1trq6m/
addRow() method now looks like:
$scope.addRow = function () {
console.log("test");
var e = new Entry();
e.id = $scope.todos.length;
e.text = $scope.content;
$scope.todos.push(e);
}