Here is example.
I simplified it as much as i could, but i still can't understand where i'm wrong.
Please help me ))
P.S stackoverflow require a code, not just link to jsfiddle, so this is it:
html:
<form action="" method="GET" data-bind="FacebookContacts">
<table class="importContacts table import">
<thead>
<tr>
<td></td>
<td>Photo</td>
<td>Name</td>
<td>Login</td>
</tr>
</thead>
<tbody data-bind="foreach: contacts">
<tr>
<td>
<span data-bind="text:FullName"></span>
</td>
<td>
</td>
<td>
</td>
<td>
</td>
</tr>
</tbody>
</table>
</form>
javascript:
var FacebookContactsViewModel = function () {
var _self = this;
_self.FacebookContacts = ko.observable();
_self.GetData = function() {
var localData=ko.mapping.fromJS(JSON.parse(contacts));
_self.FacebookContacts(localData);
ko.applyBindings(_self);
};
_self.GetData();
};
var contacts='{"contacts":[{"FullName":"Petr Perelygin"}]}';
var vm = new FacebookContactsViewModel();
Take a look at here and make your code more simpler and easier to read:
http://jsfiddle.net/NpK3K/24/
The problem was that you are putting an object into the "FacebookContacts" property and not an Array. So you should use the "with" binding extension at the first place for root element to change the datacontext for nested elements.
Hope it helps.
Related
I have the following in my View:
<div data-bind='foreach: providers'>
<div data-bind='text: name'></div>
<button data-bind='click: model.addToCart'>Show</button>
<table class="table">
<thead>
<th style="width: 300px">Name</th>
<th>Price</th>
<th></th>
</thead>
<tbody data-bind='foreach: items'>
<tr>
<td data-bind='text: name'></td>
<td data-bind='text: price'></td>
<td>
<input type="button" data-bind='click: model.add' value="Add">
</td>
</tr>
</tbody>
</table>
</div>
And the following in my model:
function model() {
var self = this;
self.providers = data; //some random array data
self.addToCart = function(place) {
console.log(place);
}
};
I have used the normal click binding in the Knockout.js.
When I run the code, it seems that the addToCart function is not even being called. I get no output from console.log() for any value.
What have I missed? I'm a beginner. Please help out.
Once inside a foreach loop, your scope is the object you're currently iterating on. So, to refer to a function in the parent or root scope you're gonna have to use $root (although $parent is the same in this case):
<button data-bind='click: $root.addToCart'>Show</button>
See Documentation
your parent View Model should have
var self = this;
self.providers = ko.observableArray();
self.model = new Model();
then in your foreach loop you can use
$root.model.addToCart()
Here's what I'm trying to do:
I have a table set up as follows:
<tbody id="entryTable" class="entryHead">
<tr id="1">
<td id="1">1</td>
<td class = driver></td>
<td><div id="button">Clear!</div></td>
</tr>
<tr id="2">
<td>2</td>
<td class = driver></td>
<td><div id="button">Clear!</div></td>
</tr>
<tr id="3">
I'm trying to get the information from this form to fill in the tables:
<form>
Driver Name:<br>
<input type="text" name="name">
<br>
Driver Draw:<br>
<input type="text" name="draw">
<div id="button">Add!</div>
</form>
I've written this bit of jquery to try to do that:
var main = function () {
$('#button').click(function ( ) {
var name = $('input[name=name]').val();
var draw = $('input[name=draw]').val();
var clear = "clear";
var draw2 = "#"+draw;
console.log(draw2);
$("draw2").getElementById(".driver").innerHTML = name;
}
)};
When I press the "Add" button I've made, I get the error "Uncaught Type Error: undefined is not a function" that points to .getElementByID.
Maybe I'm approaching it all wrong, but I'm trying to get the name of the driver to appear in the for the with the id of the number the driver drew.
Any ideas?
You're using jQuery, and you cannot use the standard getElementById on a jQuery collection object. You can use .find() instead, or get the real Element at some index. Here are two solutions:
$("selector").find("#your-id");
// or
$("selector")[0].getElementById("your-id");
Since, its jquery, it has the following syntax:
$(<selector>).function()...;
where, <selector> is the selector of the object(.class and #id).
so, instead of $("draw2").getElementById(".driver").innerHTML = name; use this:
$(".driver").html(name); or, $(".driver").text(name);
Make your code as simple as possible.
Try this, first edit your HTML code. Put a different class for your two elements that contains the driver class:
<tbody id="entryTable" class="entryHead">
<tr id="1">
<td id="1">1</td>
<td class = driverName></td>
<td><div id="button">Clear!</div></td>
</tr>
<tr id="2">
<td>2</td>
<td class = driverDraw></td>
<td><div id="button">Clear!</div></td>
</tr>
Then edit your Javascript to something like this:
$(function () {
$('#button').click(function ( ) {
var name = $('input[name=name]').val();
var draw = $('input[name=draw]').val();
$(".driverName").html(name);
$(".driverDraw").html(draw);
}
)};
if .html() wont work then change it to .text()
$(".driverName").text(name);
$(".driverDraw").text(draw);
Just a tip: When using jQuery dont combine syntax from javascript cause it will just give you errors. Instead, search for the jQuery equivalent of the javascript function: like innerHTML = 0 on native javascript is only .html(0) on jQuery or getElementById on native javascript is just simply a $ sign in jQuery.
I got it to work. Here's what I ended up doing, and a summary of the project.
This is my first JavaScript/JQuery project. I'm trying to write a program for a race track I race at that will create an entry list, calculate the heat lineups based on the number the driver randomly drew when entering, and then calculate feature lineups based on their results from the heats.
Here's the form the official will use to add each driver. The "add" button will run the jQuery script to fill the driver name into the row in the table equal to the number they drew.
<form>
Driver Name:<br>
<input type="text" name="name">
<br>
Driver Draw:<br>
<input type="text" name="draw">
<div id="button">Add!</div>
</form>
A sample of the table:
<thead>
<tr class="entryHead">
<th>Draw</th>
<th>Driver Name</th>
<th>clear</th>
</tr>
</thead>
<tbody id="entryTable" class="entryHead">
<tr id="1">
<td>1</td>
<td class = "driver1" ></td>
<td><div id="button">Clear!</div></td>
</tr>
<tr id="2">
<td>2</td>
<td class = "driver2"></td>
<td><div id="button">Clear!</div></td>
</tr>
<tr id="3">
<td>3</td>
<td class = "driver3"></td>
<td><div id="button">Clear!</div></td>
</tr>
<tr id="4">
<td>4</td>
<td class = "driver4"></td>
<td><div id="button">Clear!</div></td>
</tr>
<tr id="5">
<td>5</td>
<td class = "driver5"></td>
<td><div id="button">Clear!</div></td>
</tr>
I have 60 rows in total. Right now, the ID doesn't do anything... I just left it there because I had it there earlier while I was experimenting, and I'm leaving it there in case it's useful earlier.
Then there's the classes "driver1", "driver2", "driver3", etc. That is for jQuery to use.
Here's my jQuery script:
function Driver(draw, name) {
this.draw = draw;
this.name = name;
}
var main = function () {
$('#button').click(function ( ) {
var name = $('input[name=name]').val();
var draw = $('input[name=draw]').val();
var clear = "clear";
var draw2 = "#"+draw;
var name2 = ".driver"+draw
console.log(draw2);
console.log(name2);
$(name2).text(name);
});
}
$(document).ready(main);
I'm making an object called "Driver" that I will use later. Right now, it's just there.
Creating the variable "name2" allows "$(name2).text(name);" to find the appropriate class in the row equal to "draw", and put the driver's name in that draw. For example, if Jeff Gordon draws 24, his name would go in row 24, and the "name2" variable for him would end up being "name24".
Does that make sense?
I got this part to work for now. Thanks for your help.
I have an big table I need to create multiple times in the same page, but I'm not sure have to do. I thought the easiest way is to have the table as an partial view hidden on the page, and each time I need it I will clone it from my jQuery code. I know have to clone it, but I'm not sure have to insert the text into the specific span's, before I insert it.
This is a small example of my table. Can somebody help me with this problem
< div id="ToClone">
<table >
<tr>
<td>
<table>
<tr><td><b>MMS_RepairLabel:</b></td><td align="right"><span id="RepairId"></span></td></tr>
<tr><td><b>MMS_MWTLabel:</b></td><td align="right"><span id="MWT"></span></td></tr>
<tr><td><b>MMS_MDTLabel:</b></td><td align="right"><span id="MDT"></span></td></tr>
</table>
</td>
</tr>
</table>
</div>
<script>
var History = (function () {
$(function () {
var tblClone = $("#ToClone").clone();
});
}());
</script>
You will need to resolve the problem of duplicate ids first. I suggest changing them to classes.
I recommend a little trick of using a dummy script block for your template. This is great for maintenance and browsers just ignore the unknown type so you can insert any elements:
<script id="ToClone" type="text/template">
<table>
<tr>
<td>
<table>
<tr>
<td><b>MMS_RepairLabel:</b>
</td>
<td align="right"><span class="RepairId"></span>
</td>
</tr>
<tr>
<td><b>MMS_MWTLabel:</b>
</td>
<td align="right"><span class="MWT"></span>
</td>
</tr>
<tr>
<td><b>MMS_MDTLabel:</b>
</td>
<td align="right"><span class="MDT"></span>
</td>
</tr>
</table>
</td>
</tr>
</table>
</script>
Then clone with your inserted values like this:
var $clone = $($('#ToClone').html());
$('.RepairId', $clone).text(repairIdValue);
$('.MDT', $clone).text(mdtValue);
$('.MWT', $clone).text(mwtValue);
// Do something with the clone
JSFiddle: http://jsfiddle.net/TrueBlueAussie/381ugdvr/1/
If i can get what you are looking for, look this solution:
jQuery:
$('.pasteTable').each(function(){
var RepairId = $(this).data('repair-id');
var MWT = $(this).data('mwt');
var MDT = $(this).data('mdt');
$(this).html('<table><tr><td><b>MMS_RepairLabel:</b></td><td align="right"><span class="RepairId">' + RepairId + '</span></td></tr><tr><td><b>MMS_MWTLabel:</b></td><td align="right"><span class="MWT">' + MWT + '</span></td></tr><tr><td><b>MMS_MDTLabel:</b></td><td align="right"><span class="MDT">' + MDT + '</span></td></tr></table>');
});
Anywhere in your code you want the table to be cloned, just insert a with 'data' attributes:
HTML:
<div class="pasteTable" data-repair-id="#1" data-mwt="baby" data-mdt="ball"></div>
Demo:
http://jsfiddle.net/zf09m0at/3/
I'm trying to build a template for a application and want to display a dynamic list with names. so i got this code to show the list and add/remove rows;
<table ng-init="page.businessRows = []">
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Phone</th>
</tr>
</thead>
<tr ng-repeat="row in page.businessRows">
<td>
<input type="text" ng-model="row.name" />
</td>
<td>
<input type="text" ng-model="row.contact" />
</td>
<td>
<input type="text" ng-model="row.phone" />
</td>
<td>
<button ng-click="page.businessRows.splice($index,1)">
Remove
</button>
</td>
</tr>
</table>
<button class="btn" ng-click="page.businessRows.push({})">addRow</button>
the thing as that when this template is loaded page.busnessRows will most likely be loaded with rows so i want to change the ng-init to only create the empty array if businessRows is not initialised.
I have tried ng-init="page.businessRows = page.businessRows.length < 1 ? [] : page.businessRows but it did not work. How am i inteded to do conditions in jsangular expressions?
All help appreciated. Thanks in advance
You can do this instead:
<table ng-init="page.businessRows = page.businessRows || []">
Update
I look at the parser code of AngularJS and notice that version 1.2 (currently RC) supports ternary expression. So if you use AngularJS 1.2, this will also work (although more verbose than the above code):
<table ng-init="page.businessRows = page.businessRows == null ? [] : page.businessRows">
See demo here.
However, your original code might not work if page.businessRows is null, because the parser will fail to dereference length property of null. So just be careful there.
I don't think the ng-init will evaluate conditional statements properly. But you could refactor the condition into a controller function and call the function from ng-init.
<table ng-init="initializeBusinessRows(page.businessRows)">
The just put your conditional evaluation in the function on the controller scope.
I think you're trying to solve the wrong problem.
The problem is that you're allowing an action to occur before the data is loaded or ready. A secondary problem is you're using an expression in an ng-click where a scope function or controller function should be.
So...
Disable that button if the form isn't ready.
Use your controller to control these interactions.
So here's an example of the controller. The $timeout was added to simulate a delayed load of data into your $scope.page variable.
app.controller('MyCtrl', function($scope, $timeout, $window) {
//Timeout to simulate the asynchronous load
//of the page object on the $scope
$timeout(function(){
$scope.page = {
businessRows: []
};
}, 2000);
//scope method to add a row.
$scope.addRow = function (){
//for safety's sake, check to see if the businessRows array is there.
if($scope.page && angular.isArray($scope.page.businessRows)) {
$scope.page.businessRows.push({});
}
};
//scope method to remove a row
$scope.removeRow = function(index, row) {
if($window.confirm('Are you sure you want to delete this row?')) {
$scope.page.businessRows.splice(index, 1);
}
};
});
... and the HTML view (notice the ng-disabled and the ng-click) (and lack of ng-init):
<div ng-controller="MyCtrl">
<table>
<thead>
<tr>
<th>Company</th>
<th>Contact</th>
<th>Phone</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in page.businessRows">
<td>
<input type="text" ng-model="row.name" />
</td>
<td>
<input type="text" ng-model="row.contact" />
</td>
<td>
<input type="text" ng-model="row.phone" />
</td>
<td>
<button ng-click="removeRow($index, row)">
Remove
</button>
</td>
</tr>
</tbody>
</table>
<button class="btn" ng-disabled="!page" ng-click="addRow()">addRow</button>
</div>
Also, here's the obligatory Plunker for you to see this in action.
Suppose I have already get the table with JavaScript like this:
var isert = inn.getElementsByTagName("table");
and I've got a structure like this:
<table width="100%">
<tbody>
<tr>
<td><div class="extra"></div>
</td>
</tr>
<tr>
<td><div class="extra"></div>
</td>
</tr>
<tr>
<td><div class="extra"></div>
</td>
</tr>
</tbody>
</table>
Here, how can I remove the outside Table structure, and keep the content only, so that result of the extracted code should be:
<div class="extra"></div>
<div class="extra"></div>
<div class="extra"></div>
Thanks!
I'd suggest:
function removeTo(from, what) {
if (!from || !what) {
return false;
}
else {
els = from.getElementsByTagName(what);
while (els[0]) {
from.parentNode.insertBefore(els[0],from);
}
from.parentNode.removeChild(from);
}
}
removeTo(document.getElementsByTagName('table')[0], 'div');
JS Fiddle demo.
Incidentally:
var isert = inn.getElementsByTagName("table");
Doesn't give you a reference to the table element, it gives you a nodeList of all the table elements within the inn variable (whatever that might be). To act on a particular table you need to specify which particular table you want to act upon, which is why, above, I've used document.getElementsByTagName('table')[0].