CRUD knockout js - javascript

I know this is too much to ask but I cannot find any good tutorials on what I am doing.
I am getting data from the database and using foreach on the html page to show the fields. Like this.
<script type="text/javascript" src="<?php echo base_url();?>js/learnKO.js?<?php echo date('l jS \of F Y h:i:s A');?>" ></script>
<div class="table-responsive">
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th class="text-center">1</th>
<th class="text-center">2</th>
<th class="text-center">3</th>
</tr>
</thead>
<tbody data-bind="foreach: alldata">
<tr>
<td class="text-center"><span data-bind="text: $data.net_amount "></span></td>
<td class="text-center"><span data-bind="text: $data.vat_amount"></span></td>
<td>
<button type="button" class="btn btn-default btn-xs" data-bind="click: $parent.editItem">Edit</button>
<button type="button" class="btn btn-default btn-xs" data-bind="click: $parent.acceptItem">Accept</button>
<button type="button" class="btn btn-default btn-xs" data-bind="click: $parent.cancelItem">Cancel</button>
</td>
</tr>
</tbody>
</table>
</div>
My js file includes a simple function, which gets the data like this.
self.alldata = ko.observableArray();
self.viewAllInvoice = function () {
$.ajax({
type: 'POST',
url: BASEURL + 'index.php/moneyexchange/learn_Ko/' ,
contentType: 'application/json; charset=utf-8'
})
.done(function(invoices) {
self.alldata.removeAll();
$.each(invoices, function (index, invoice) {
self.alldata.push(invoice);
});
})
.fail(function(xhr, status, error) {
alert(status);
})
.always(function(data){
});
};
self.viewAllInvoice();
And I am using phpcode igniter for getting the data. Here is how I get from the controller and model.
public function learn_Ko(){
$this->load->model('invoice_page');
$result = $this->invoice_page->getAllInvoice();
$this->output->set_content_type('application/json');
$this->output->set_output(json_encode($result));
}
And here is the model
public function getAllInvoice(){
$query ='SELECT * FROM invoice';
$query = $this->db->query($query);
$result = $query->result();
return $result;
}
What I want to do is just edit the table and the edited data to be stored in the database. Please do guide me in steps since I tried a lot of different tutorials but couldn't do it. I provided everything here so I am sure I am not missing anything.
This is the table pic

For a JavaScript CRUD app, I'd use an OData service in the server (I'm sure there must be some implementations in PHP, for example see: How to create an Odata Service using PHP?) and the wonderful breeze.js library.
Breeze.js handles all the CRUD stuff, and communication with the OData service in a very easy and powerful way. And get ons very well with knockout: you simply have to load the konockout library before breeze, so that breeze detects it. If you do so, breeze will generate observable properties automatically for you from the data recevied from the OData service. And allows to validate, track changes, send changes in a batch and many more things.

Related

asp-route always uses the first Id of html for each loop because of javascript dialog

I am displaying data from my c# backend with a for each loop in the html page. When deleting an element, I am opening a modal dialog to confirm. But because this involves javascript, the delete function after the confirmation always is the one for the first item of my data. So it seems that the calling of javascript restarts the for each loop.I always get the first id in the backend.
The relevant html code:
<form method="post">
<table class="table table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
</tr>
</thead>
<tbody>
#foreach (var experiment in Model.MainExperimentsTests)
{
<tr>
<td>#experiment.Id</td>
<td>#experiment.ExperimentTestName</td>
<td>
<a class="btn permissionRead permissionWrite"
onclick="showDeleteDialog()">
<i class="bi-bucket"></i>
</a>
<dialog id="deleteDialog">
Do you really want to delete?
<button asp-page-handler="Delete" asp-route-experimentId="#experiment.Id"
value="confirm">Ok</button>
<button onclick="closeDeleteDialog()" type="reset">Cancel</button>
</dialog> </td>
</tr>
}
</tbody>
</table>
</form>
Javascript code:
<script>
function showDeleteDialog() {
document.getElementById("deleteDialog").showModal();
}
function closeDeleteDialog() {
document.getElementById("deleteDialog").close();
}
</script>
I tried saving the id in javascript and doing an ajax post call from there instead of using the "asp-page-handler" and "asp-route-experimentId", but I couldn't get it to work properly. I tried different ways to open a dialog, but I don't want the default pop up from the browser, I want my own modal dialog.
Does anyone know how I can get the right id to be passed to asp-route? Is my structure completely wrong?
I appreciate your help.
You need unique dialog ids. For example you can concat experiment id to the dialog id. Try something like the following:
<a class="btn permissionRead permissionWrite" onclick="showDeleteDialog(#experiment.Id)">
<i class="bi-bucket"></i>
</a>
<dialog id="deleteDialog_#experiment.Id">
...
<button onclick="closeDeleteDialog(#experiment.Id)" type="reset">Cancel</button>
</dialog>
<script>
function showDeleteDialog(experimentId) {
document.getElementById("deleteDialog_" + experimentId).showModal();
}
function closeDeleteDialog(experimentId) {
document.getElementById("deleteDialog_" + experimentId).close();
}
</script>

Laravel duplicated view after selecting dropdown option

I have a problem with my Laravel view. I am getting the desired data through ajax and I can also show that data in my view. However, I found that whenever I select something in my dropdown then the data appears, but the overall layout gets duplicated. I see my console and find that inside the table I have another layout created after selecting something with the dropdown. I have my code here please take a review of it.
<select>`enter code here`
#foreach(App\StudentsClass::all() as $class)
<option id="class{{$class->id}}" value="{{$class->id}}">{{$class->class_name}}</option>
#endforeach
</select>
<table id="studentsData" class="table table-striped table-bordered table-list-search">
<thead>
<tr>
<th>#</th>
<th>Student ID</th>
<th>Student Name</th>
<th>Attendance</th>
</tr>
</thead>
#foreach($students as $student)
<tbody>
<tr>
<th>{{$student->id}}</th>
<td>{{$student->student_id}}</td>
<td>{{$student->first_name}} {{$student->last_name}}</td>
<td>
<div class="form-group">
<select class="form-control" id="gender">
<option>Present</option>
<option>Absent</option>
<option>Leave</option>
</select>
</div>
</td>
</tr>
</tbody>
#endforeach
</table>
<a class="fas fa-folder-open btn btn-success float-right mb-4 mr-2"> Save</a>
</div>
<script>
$(document).ready(function () {
#foreach(App\StudentsClass::all() as $class)
$("#class{{$class->id}}").click(function () {
var classes = $("#class{{$class->id}}").val();
$.ajax({
url: '{{url('/students/attendance')}}',
type: "GET",
dataType: "html",
data: 'class_id=' + classes,
success:function(response) {
// console.log(response);
$('table[id=studentsData]').html(response);
}
});
});
#endforeach
});
Its hard to say without knowing exactly that is returned by the ajax call -- but it sounds like you may be returning the either a full view (Everything from <html> to </html>) and inserting it into the table ... or the full html markup for a table, creating new nested tables on each ajax call.
Can you share the result of your ajax call? (What you see with console.log(response); )
Also, I don't think this is related but noticed a few things you could do to your code to simplify. For example, Id suggest changing your dropdown's structure a bit and giving it an ID like so ...
<select id="class_select">
#foreach(App\StudentsClass::all() as $class)
<option value="{{$class->id}}">{{$class->class_name}}</option>
#endforeach
</select>
And then rather than looping through each class and adding dedicated function, you could adjust your javascript to find the class ID and trigger the ajax call each time the dropdown is changed.
<script>
$(document).ready(function(){
$('#class_select').change(function(){
var class = $(this).val();
$.ajax({
url: '{{url('/students/attendance')}}',
type: "GET",
dataType: "html",
data: 'class_id=' + classes,
success:function(response) {
// console.log(response);
$('#studentsData').html(response);
}
});
});
});
</script>
Hope that helps! If we could see what the ajax call returns I think we could give a better answer.

Thymeleaf table update without page reload

I am rendering datawith thymeleaf attribute. But i am implementing "Search" button now, and want to do it without reload.
I have attribute depatments which render List<Department> from db
I know, how to do it via ajax, but then i need to replace attribute with RestController, who will give me JSON.
Is it posible to fetch data from attribute without reloading page? Ajax, or js, or something else?
Thanks
Yes, you can achieve this by using fragment and ajax. In your controller
#GetMapping("/url")
public ModelAndView getResultBySearchKey()
{
List<depatments> areaList= new ArrayList<>();//results from db
ModelAndView mv= new ModelAndView("search::search_list");
mv.addObject("searchList",areaList);
return mv;
}
and in your search.html add bellow code. And don't forget to use inline javascript.
function loadSearchResult()
{
$.ajax({
type: 'get',
url: /*[[ #{'/url'} ]]*/,
success: function(data){
/*<![CDATA[*/
$('.search_list').html(data);
/*]]>*/
},
})
}
<button class="btn btn-primary btn-sm"
th:onclick="'loadSearchResult();'">Search</button>
<div class="row">
<div class="col-md-12 search_list">
<div class="table-responsive" th:fragment="search_list">
<table
class="table table-bordered ">
<thead>
<tr>
<th>SL No.</th>
<th>Actions</th>
<th>Name</th>
</tr>
</thead>
<tbody>
<!-- your desired rows-->
</tbody>

How to save all rows of a dynamic table in AngularJS?

I am trying to add the rows dynamically for one of the variables which is of type String array in my db. But it only saves the last value entered in the row rather than saving all of them in an array. Below is my view code:
<div class="row" ng-class='{red:true}'>
<label for="remedy">Remedy</label>
</div>
<input name="remedy" id="remedy" ng-model="error.remedy" required>
<br/>
<div class="row" ng-class='{red:true}'>
<a href="#!/errorcreate" class="btn btn-primary btn-small" ng-click="addRemedyRow()" ng-class='{red:true}'>Add Row</a></div>
<br/>
<table style="width:100%">
<thead>
<tr>
<th ng-class='{red:true}'>Remedy</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="rowContent in remedyrows">
<td>{{rowContent.remedy}}</td>
</tr>
</tbody>
</table>
{{error.remedy}}
<button type="submit" class="btn btn-default">Create</button>
Cancel
And this is the code in javascript:
$scope.remedyrows = [];
$scope.addRemedyRow = function() {
$scope.remedyrows.push({
remedy: $scope.error.remedy
});
Below is the output I am receiving (in a screenshot):
I added dsdfg as second row and my final error.remedy value just shows dsdfg rather than showing an array of both values : [wdssdsd,dsdfg]. error is the main document of which remedy is one of the fields of type String array.
Any ideas on how to achieve this?
Instead of error.remedy, which is used as holder for future remedyrow, use intermediate variable output for displaying results and sending them to the server:
Javascript:
$scope.output = $scope.remedyrows.map(function(x) { return x.remedy; });
$http({data: $scope.output, method: 'POST', url: url});
HTML:
{{output | json}}
you could have achieved it by following way:
$scope.remedyrows = [];
$scope.output;
$scope.addRemedyRow = function() {
$scope.remedyrows.push({
remedy: $scope.error.remedy
});
$scope.output = $scope.remedyrows.toString();
}
and in html
{{output}}

How to avoid creating new row in table after javaScript call?

I'm building a laravel application where I want to show if there is any update data in database after two seconds.So in this scenario I have given the table a 'id' and then I have laod the table after certain time interval. But the problem is after every javascript call it creates an empty row in table even if the table retrieve the value also. How do I avoid the problem..any suggestion please?
<div class="container">
<h3> List Of Courses </h3></br>
<table class="table table-striped table-bordered dataTable" id="example">
<thead>
<tr>
<td>Serial No</td>
<td>Title</td>
<td>Description</td>
<td>Action</td>
</tr>
</thead>
<tbody>
<?php $i=1; ?>
#foreach($items as $row)
<tr>
<td>{{$i}}</td>
<td class="title" data-id1="{{$row->id}}" contenteditable>{{$row->title}}</td>
<td class="description" data-id2="{{$row->id}}" contenteditable>{{$row->description}}</td>
<td>
<button type="button" onclick="deleteItem({{ $row->id }})" class="btn btn-danger">Delete</button>
</td>
</tr>
<?php $i++; ?>
#endforeach
</tbody>
</table>
</div>
Here is the javascript I have to use to load the table after 3 seconds:
<script type="text/javascript">
setInterval(function() {
$("#example").load("list #example");
}, 30000);
</script>
You need to give load a callback and check if you returned any data.
Without knowing the return data structure my best guess would be
$("#example").load("list #example", function (data) {
// hopefully you are returning json. if not, return json. It's the artisan way :D
let parsed = JSON.parse(data);
if (parsed) {
// build html and inject in dom
}
});
See this is how I actually solved the problem,
I put the table inside a new div and I called the jquery .load() on that div.
Like this :
<div class="reloadTable">
<table class="table table-striped table-bordered dataTable" id="example">
// table data
</table>
</div>
javaScript :
<script type="text/javascript">
setInterval(function() {
$(".reloadTable").load("list #example");
}, 3000);
</script>

Categories