KnockoutJS submit binding not working with foreach - javascript

Hello I am unable use knockout 'submit' binding with 'foreach' binding.
I cannot figure out what is mistake here.
Please help me find my mistake.
My view model is like this:
function poReceivingModel(){
var self = this;
var initial_row = new poReceivingRowModel();
self.rows = ko.observableArray([initial_row]);
self.saveAndAdd = function(formElement){
alert('entered into function');
var row = new poReceivingRowModel();
self.rows.push(row);
};
};
function poReceivingRowModel(){
var self = this;
self.building = ko.observable();
self.isele_abc = ko.observable();
self.isele_num = ko.observable();
self.isele_floor = ko.observable();
};
And my html binded to 'viewmodel' is like this:
<tbody data-bind="foreach: rows">
<form data-bind="submit: $parent.saveAndAdd">
<tr>
<td>
<!-- input field here -->
</td>
<td>
<!-- input field here -->
</td>
<td>
<!-- input field here -->
</td>
<td>
<!-- input field here -->
</td>
<td>
<button type="submit">Save and Add</button>
</td>
</tr>
</form>
</tbody>
The problem is when I click on 'Add and Save' button 'saveAndAdd' function from 'poReceivingModel' is not called.
I do not get any alert message.
I tried calling that function with 'click' binding on 'button' element. The function get called this way ie I get alert message.
UPDATE:
In firebug I see form tag is closed just after
and button is out of 'form' tag.

I found that form tag cannot be used inside table tag. Solution is table tag can be put inside form tag .
If we do not want to do so we can change the table tag to div but this may not give you desired output.

Related

AngularJS - Form good practice

So I am new to AngularJS and I am looking to create good code because my application is going to scale.
Now, I have a list of competences that I'll get from my API, and then I need to make a list of them with a checkbox, so the user will select/deselect from the list, and then submit that form.
So how can I achieve that? What should be in the ng-model of every checkbox? Should I create a form with all the values in set in false?
Here's my controller code now:
function Controller(Competence) {
var vm = this;
vm.competences = [];
function initController() {
Competence.getAll()
.then(function(data) {
vm.competences = data;
});
}
initController();
}
And here's my view code:
<table>
<thead>
<tr>
<th width="90%">Competence</th>
<th width="10%">Select</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="competence in vm.competences">
<td>{{ competence.name }}</td>
<td><input type="checkbox"></td>
</tr>
</tbody>
</table>
So far your code looks good. To set checkbox values, just add ng-model="competence.selected" to each checkbox input element like this:
<input type="checkbox" ng-model="competence.selected">
Now when you select the checkbox it will set competence.selected to true, and when you deselect it the value will be false.
Form Submission
Wrap your table in a <form> with an ng-submit attribute, and create a function to submit the form:
<form ng-controller="MyCtrl as vm" ng-submit="vm.submitForm()">
<!-- your table here ... -->
<input type="submit" value="Submit">
</form>
In your controller:
vm.submitForm = function(){
vm.competences.forEach(function(competence){
if(competence.selected) console.log(competence);
// or POST the competences using the $http service ...
})
}
See JSFiddle also: Checkbox Demo

select obsservableArray record from table in knockout

trying to figure out how to set up the radio button bindings in a table in knockout. I would like when the radio button on the table is selected. the entire selected record is available in the model. not quite sure how to set up the binding on the radio input. I assume I need to use $parent and a function for the value binding?
here is the fiddle. (the selected record does not do anything right now I would like it to be populated when the radio button is selected)
https://jsfiddle.net/othkss9s/5/
HTML
<table>
<thead>
<tr>
<th>Select</th>
<th>First</th>
<th>Last</th>
<th>Dept</th>
</tr>
</thead>
<tbody data-bind='foreach: employees'>
<tr>
<td><input type="radio" name="employees"></td>
<td data-bind='text: first'></td>
<td data-bind='text: last'></td>
<td data-bind='text: dept'></td>
</tr>
</tbody>
</table>
<div data-bind="with: selectedRow">
<h2>
Selected Record
</h2>
<p>
First: <span data-bind="first" ></span>
</p>
<p>
Last: <span data-bind="last" ></span>
</p>
<p>
Dept: <span data-bind="dept" ></span>
</p>
</div>
JS
function employee(first, last, dept) {
this.first = ko.observable(first);
this.last = ko.observable(last);
this.dept = ko.observable(dept);
}
function model() {
var self = this;
this.employees = ko.observableArray("");
this.selectedRow = ko.observable({});
};
var myViewModel = new model();
$(document).ready(function() {
ko.applyBindings(myViewModel);
myViewModel.employees.push(
new employee("Bob","Jones", "Hr")
);
myViewModel.employees.push(
new employee("Sarah","Smith", "It")
);
myViewModel.employees.push(
new employee("John","Miller", "It")
);
});
You have to perform two steps to get your code working.
First, apply bindings to radio buttons:
<input type="radio" data-bind="checked: $root.selectedRow, checkedValue: $data" />
checkedValue should contain actual value that corresponds the current radio button. In this case we refer $data variable that is whole employee object rather than simple (scalar) value.
checked binding should refer to an observable containing currently selected employee.
Second, correct the line where the selectedRow property is defined:
this.selectedRow = ko.observable();
Do not pass empty object as default value. Otherwise with binding won't work correctly.
By fixing the syntax of bindings in your second block that displays selected employee you will get something like this.

knockout if-else bind cannot work correctly

I am new to knockout, currently I met a weird problem. What I want is to use ko if-else bind, please see the code below:
<table>
<thead>
something......
</thead>
<tbody>
<tr>
Problem comes here...
<!-- ko ifnot: editing -->
<td><span data-bind="text: Value" /></td>
<td><button data-bind="click: Edit">Edit</button></td>
<!-- /ko -->
<!-- ko if: editing -->
<td><input data-bind="value: Value"></td>
<td><button data-bind="click: Save">Save</button></td>
<!-- /ko -->
</tr>
</tbody>
</table>
In ViewModel:
function SettingData(){
var self = this;
self.editing = ko.observable(false);
self.Edit = function () {
self.editing(true);
};
self.Save = function () {
self.editing(false);
}
}
When start the page, content in if and ifnot statement all come out (it should be wrong). When click "Edit", only content in if statement show up and content in ifnot statement disappear, which is good, but when click "Save", connent in if and ifnot statement all show up.
I don't know which part of my code is incorrect, can anyone give me hand? Thanks.
You must add Value observable in the viewmodel. Add below line to function SettingData()
self.Value = ko.observable("");

AngularJS, easy way to show a delete button when a checkbox is checked in the list of users under ng-repeat

I am trying to toggle a delete button which has already a function bound to it. The list is created with ng-repeat checking the users object. But the methds I have seen so far are either simple model show which does not work in my case. Or complex directive controller methods.
All I need is to check whether at least one checkbox is checked. Here is the snippet from the code:
<table class="table">
<tr ng-repeat="user in ctrl.commonUserService.users | filter:ctrl.commonUserService.suppressLoggedOnUserFilter()">
<td><input type="checkbox" ng-model="user.selected" value="y" /></td>
<td title="User Name"><strong>{{user.userName}}</strong></td>
How can I easily do this with Angular? I tried to create a function looping users and looking if they are selected at all but don't think I can put this function to ng-show.
You'll have to check if at least one box is selected when the state changes:
<td><input type="checkbox" ng-model="user.selected" ng-change="ctrl.userSelected()" value="y" /></td> <!-- use ng-change to notify when a checkbox is clicked -->
<button ng-click="ctrl.delete()" ng-show="ctrl.usersSelected">Delete</button> <!-- if ctrl.usersSelected is true show delete -->
In the controller:
this.userSelected = function userSelected() { // when checkbox is clicked check users to see if at least one is selected and save the state in this.userSelected
this.usersSelected = this.commonUserService.users.some(function(user) {
return user.selected;
});
};
You can do this fairly easily using the ng-change directive on your inputs. See this plunkr for the working example, but it basically goes like this:
View:
<table class="table">
<tr ng-repeat="user in users">
<td><input type="checkbox" ng-change="isSelected()" ng-model="user.selected" /></td>
<td title="User Name"><strong>{{user.userName}}</strong></td>
</tr>
</table>
<button class="delete" ng-show="showDelete">Delete</button>
Controller:
$scope.isSelected = function() {
var somethingSelected = false;
$scope.users.forEach(function(user, index) {
if (user.selected) somethingSelected = true;
});
$scope.showDelete = somethingSelected;
};

Validation error in Backbone Views

Ok I'm messing around with code to help me understand javascript better and Ive been playing with backbone. I may be missing it but my validation here isnt working right. I either get a "you must fill in both fields or it just submits even if a field is blank.
The function of addModel is to add a row to my parent view and save it all in one function which is causing me issues
Form = Backbone.View.extend({ //form view
el: '.item-form',
initialize: function(){
},
events: {
'click #additem': 'addModel' // clicking on the add item button launches the addmodel function
},
addModel: function(){ // when the addmodel function fires it takes
var item = new Item({
"itemName": this.$("#item").val(),//value of form input placed into row template cell
"price": this.$("#price").val()});
// simple validation before adding to collection
if(!_.isEmpty("#item") && !_.isEmpty("#price")){
var items = new Items();
items.add(item);
$("#message").html("Please wait; the task is being added.");
item.save(null, {success:
//use the mongo id as the Item models id
function (item, response,options) {
item.id= item.attributes._id.$id;
item.attributes.id = item.attributes._id.$id;
new ItemsView({collection: items});
$("#message").html("");
}
});
this.$("#item").val('');//all this does is empty the field
this.$("#price").val('');//all this does is empty the field
} else {
alert('Please fill in both fields');
}
}
});
heres the html for reference
<body>
<table class="itemTable">
<thead>
<tr>
<th>Item</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody class="tableBody">
<script type="text/template" id="table-row">
<td><%= itemName %></td> <td><%= price %></td> <td> <button class="complete">Complete</button> <button class="remove">Remove</button></td>
</script>
</tbody>
</table>
<form class="item-form">
<input type="text" name="item" id="item" placeholder="Item"/> <!-- goes to itemName in the template for the body -->
<input type="text" name="price" id="price" placeholder="Price" /><!--goes to price in the template for the body -->
<button type="button" id="additem">Add</button>
</form>
<div id="message"></div
The validation should compare the values of the inputs not simply the id's.
if(!_.isEmpty(this.$("#item").val()) && !_.isEmpty(this.$("#price").val())){

Categories

Resources