Backbone js and elements - javascript

I am currently working on a data input form that will take as in input some time parameters. As a result, I desire to use a jquery timepicker in these fields, within the itemview. This is my first time attempting to interact with the internal elements of an itemview and assistance would be greatly appreciated.
This is what i have attempted so far.
<div class="grid_15 top-m">
<div class="grid_16"><h3>Class Sessions</h3> <i>(eg. Period 1, Period 2 etc)</i></div>
<div class="grid_16">
<div id="sessionlist"></div>
<br/><br/>
</div>
<div>
<a id="addses" class="top-m" href="#">Add</a>
<a id="removeses" class="top-m" href="#" style="display:none" >Remove</a>
</div>
</div>
The add and remove buttons remove and add itemviews as desired.
<script type="text/html" id="SFTemplate">
<div class="editor-label">
<label for="Sessions[{{ count }}].Name">Session Name</label>
</div>
<div class="editor-field">
<input type="textbox" id="Sessions[{{ count }}].Name" name="Sessions[{{ count }}].Name"/>
</div>
<div class="editor-label">
<label for="Sessions[{{ count }}].StatTime">Session Start Time</label>
</div>
<div class="editor-field">
<input type="textbox" id="Sessions[{{ count }}].StartTime" name="Sessions[{{ count }}].StartTime"/>
</div>
<div class="editor-label">
<label for="Sessions[{{ count }}].EndTime">Session End Time</label>
</div>
<div class="editor-field">
<input type="textbox" id="Sessions[{{ count }}].EndTime" name="Sessions[{{ count }}].EndTime"/>
</div>
That is the template for the itemview
<script>
window.CreateSession = (function () {
var CreateSession = {};
var ses = new Array();
//The next of kin item list view
SessionItemView = Backbone.View.extend({
tagName: 'div',
initialize: function () {
//bindall
_.bindAll(this, 'render');
this.template = _.template($('#SFTemplate').html());
this.render();
},
render: function () {
$(this.el).html(this.template({
count: ses.length
})).fadeIn();
return this;
},
remove: function () {
$(this.el).fadeOut('fast', function () {
$(this).remove();
});
return false;
},
**events: {
"click input[type=textbox]": "placetimepicker"
},
placetimepicker: function (e) {
e.el.timepicker({ ampm: true,
hourMin: 8,
hourMax: 16
});**
}
});
function sesUpdated() {
if (ses.length > 0) {
$('#removeses').fadeIn();
}
else {
$('#removeses').fadeOut();
}
}
CreateSession.Init = function () {
$('#addses').click(function () {
var item = new SessionItemView();
ses.push(item);
$('#sessionlist').append($(item.el).fadeIn('fast'));
sesUpdated();
return false;
});
$('#removeses').click(function () {
if (ses.length > 0) {
ses.pop().remove();
}
sesUpdated();
return false;
});
};
return CreateSession;
})(this, this.document);
$(function () {
CreateSession.Init();
});

After more research and trial and error, I found where my code was lacking.
**events: {
"click .timepicker": "placetimepicker"
},
placetimepicker: function () {
this.$(".timepicker").timepicker({ ampm: true,
hourMin: 8,
hourMax: 16
});**
}
});
I put a class timepicker on the textboxes and using the 'this' keyword I could append the jquery code unto the entire itemview.
Backbone is cool. :-D

It's difficult to determine your question. What I think your asking is why the timepicker is not initializing for your inputs. Try wrapping your event element in jquery $(e.el) since your timepicker is a jquery plugin:
placetimepicker: function (e) {
$(e.el).timepicker({ ampm: true,
hourMin: 8,
hourMax: 16
});

Related

Uncaught TypeError: Unable to process binding "if" with knockout

I am simply trying to create some checkboxes and inputs that get the data from database and saving it back to database after edit. But I am getting the following error:
Uncaught TypeError: Unable to process binding "if: function(){return $root.editAlarmValues }"
Message: Unable to process binding "enable: function(){return $root.editAlarmValues().setAlarmValues() }"
Message: $root.editAlarmValues(...).setAlarmValues is not a function
I am not sure what I am doing wrong. I checked in the console and the values get mapped correctly to the array but they don't seem to bind to view. Any help will be highly appreciated!
Here is the code:
<!--ko if: $root.editAlarmValues -->
<div class="row">
<div class="col-md-6">
<input type="checkbox" data-bind="iCheck: $root.editAlarmValues().setAlarmValues" class="large-check"/>
</div>
</div>
<div class="row">
<div class="col-md-5 form-inline">
<input type="checkbox" data-bind="iCheck: $root.editAlarmValues().setOutputCurrentPPLowValue, enable: $root.editAlarmValues().setAlarmValues()" class="large-check"/>
<input type="text" id="OutputCurrentPPLowValue" data-bind="value: $root.editAlarmValues().outputCurrentPPLowValue, enable: $root.editAlarmValues().setOutputCurrentPPLowValue()" class="form-control" maxlength="30" />
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="pull-right">
<button type="button" class="btn btn-primary btn-flat" data-bind="event: {click: $root.editSave}">Save</button>
</div>
</div>
</div>
<!-- /ko -->
and script:
var AlarmsViewModel = function (wellID) {
function EditAlarms(setAlarmValues, setOutputCurrentPPLowValue, outputCurrentPPLowValue) {
var self = this;
self.setAlarmValues = ko.observable(setAlarmValues);
self.setOutputCurrentPPLowValue = ko.observable(setOutputCurrentPPLowValue);
self.outputCurrentPPLowValue = ko.observable(outputCurrentPPLowValue);
}
var self = this;
self.wellID = ko.observable(wellID);
self.editAlarmValues = ko.observableArray();
self.init = function () {
self.editAlarmInit();
};
self.editAlarmInit = function () {
APIHelper.getData("/api/alarmapi/EditAlarms?wellID=" + self.wellID(), self.editAlarmsCallback, "");
};
self.editAlarmsCallback = function (data) {
//Map results
var temp = $.map(data.result, function (item) {
return new EditAlarms(item.setAlarmValues, item.setOutputCurrentPPLowValue, item.outputCurrentPPLowValue);
});
self.editAlarmValues(temp);
};
self.editSave = function () {
var jsonData = ko.toJSON(self.editAlarmValues);
APIHelper.postData("/api/alarmapi/EditAlarmsPost", jsonData);
};
self.init();
};
var wellID = #ViewBag.WellID;
ko.bindingHandlers.iCheck = {
init: function (el, valueAccessor) {
var observable = valueAccessor();
$(el).on("ifChanged", function () {
observable(this.checked);
});
},
update: function (el, valueAccessor) {
var val = ko.utils.unwrapObservable(valueAccessor());
if (val) {
$(el).iCheck('check');
} else {
$(el).iCheck('uncheck');
}
}
};
var vm = new AlarmsViewModel(wellID);
ko.applyBindings(vm);
You don't want a <!-- ko if: editAlarmValues -->, you want a <!-- ko foreach: editAlarmValues -->. The foreach will not run when the target array is empty, so it fundamentally fulfills the same function.
Inside the foreach, the binding context is the EditAlarms object in question, so you should refer to its properties directly (iCheck: setOutputCurrentPPLowValue instead of iCheck: $root.editAlarmValues().setOutputCurrentPPLowValue).
Also think about your naming. EditAlarms is not a good name for a single object. The prefix set... should refer to a method that sets something. In this case it's just an observable property. setAlarmValues should be called alarmValues, and because it's not an array, it probably should actually be called alarmValue. And so on.
<!-- ko foreach: editAlarmValues -->
<div class="row">
<div class="col-md-6">
<input type="checkbox" data-bind="iCheck: setAlarmValues" class="large-check">
</div>
</div>
<div class="row">
<div class="col-md-5 form-inline">
<input type="checkbox" class="large-check" data-bind="
iCheck: setOutputCurrentPPLowValue,
enable: setAlarmValues
">
<input type="text" id="OutputCurrentPPLowValue" class="form-control" maxlength="30" data-bind="
value: outputCurrentPPLowValue,
enable: setOutputCurrentPPLowValue
">
</div>
</div>
<div class="row">
<div class="col-md-12">
<div class="pull-right">
<button type="button" class="btn btn-primary btn-flat" data-bind="click: $root.editSave">Save</button>
</div>
</div>
</div>
<!-- /ko -->
Revised JS code (move the binding handler definitions to the top, don't nest viewmodels)
ko.bindingHandlers.iCheck = {
init: function (el, valueAccessor) {
var observable = valueAccessor();
$(el).on("ifChanged", function () {
observable(this.checked);
});
},
update: function (el, valueAccessor) {
var val = ko.unwap(valueAccessor());
$(el).iCheck(val ? 'check' : 'uncheck');
}
};
function EditAlarms(setAlarmValues, setOutputCurrentPPLowValue, outputCurrentPPLowValue) {
this.setAlarmValues = ko.observable(setAlarmValues);
this.setOutputCurrentPPLowValue = ko.observable(setOutputCurrentPPLowValue);
this.outputCurrentPPLowValue = ko.observable(outputCurrentPPLowValue);
}
function AlarmsViewModel(wellID) {
var self = this;
self.wellID = ko.observable(wellID);
self.editAlarmValues = ko.observableArray();
self.editAlarmInit = function () {
APIHelper.getData("/api/alarmapi/EditAlarms?wellID=" + self.wellID(), function (data) {
var alarms = data.result.map(item => new EditAlarms(
item.setAlarmValues,
item.setOutputCurrentPPLowValue,
item.outputCurrentPPLowValue
));
self.editAlarmValues(alarms);
});
};
self.editSave = function () {
APIHelper.postData("/api/alarmapi/EditAlarmsPost", ko.toJSON(self.editAlarmValues));
};
self.editAlarmInit();
}
var vm = new AlarmsViewModel(#ViewBag.WellID);
ko.applyBindings(vm);

Prevent dynamic added selects from changing other divs behavior

I have an array of phones that I loop through in my razor to display them one by one on button click from a partial. Each phone has a dropdown for international and domestic phone values. On change of the dropdown, I need to hide some textboxes and show some others. I got it to work showing and hiding textboxes, but the issue now is that each dropdown will change all phones sections and it should only affect the one within its div.
Here's my view:
#for (int x = 0; x < Model.Phones.Count; x++)
{
#Html.EditorFor(m => m.Phones[x], "_PhonePartial")
}
Here's the code to show the phone partial on the button click, which hides all of them except the first one:
$('.phone-wrapper').hide();
$('.phone-wrapper').first().show();
var count = 1;
$('.add-phone-wrapper').on('click', function () {
$('.phone-wrapper:eq('+ count+')').show();
count++;
});
Here's the partial phone view:
<div class="phone-wrapper">
<div class="col-md-1 domestic-phone">
#Html.TextBoxFor(m => m.AreaCode)
</div>
<div class="col-md-1 domestic-phone">
#Html.TextBoxFor(m => m.code2)
</div>
<div class="col-md-1 domestic-phone">
#Html.TextBoxFor(m => m.code3)
</div>
<div class="col-md-3 international-phone">
#Html.TextBoxFor(m => m.Internationalbox)
</div>
<div class="col-md-3">
<select class="form-control phone-selection">
<option selected="selected" value="domestic">Domestic</option>
<option value="international">International</option>
</select>
</div>
</div>
The Javascript for hiding and showing the textboxes is:
$(function () {
$(".phone-selection").on("change", function () {
var $this = $(this),
$closeDiv = $this.closest(".phone-section");
if ($this.val().toLowerCase() === "domestic") {
$closeDiv.find(".domestic-phone").show();
$closeDiv.find(".international-phone").hide();
} else {
$closeDiv.find(".domestic-phone").hide();
$closeDiv.find(".international-phone").show();
}
});
});
Any help will be greatly appreciated, thanks!
Try this
$(function () {
$(".phone-selection").on("change", function () {
var $this = $(this),
$closeDiv = $this.closest(".phone-section");
if ($this.val().toLowerCase() === "domestic") {
$(".domestic-phone").each(function () {
$(this).show();
});
$(".international-phone").each(function () {
$(this).hide();
});
} else {
$(".domestic-phone").each(function () {
$(this).hide();
});
$(".international-phone").each(function () {
$(this).show();
});
}
});
});

Manually set the focus on input element in angular js

I create one input element and on click show the list of items after selecting any item list get hide.
But the focus is not on that element it get down,
So I just want to manually set the focus on input element when radio button list get hide.
Here is use the following code,
View
<label class="item item-input item-stacked-label" ng-click="showDays()">
<span class="input-label black-text">DAYS</span>
<span class="input-ctrl">
<input type="text" id="days" readonly ng-model="data_day" focus-on="!daysflag">
</span>
</label>
<div ng-show="daysflag">
<ion-radio icon="ion-ios-checkmark" ng-model="data_day" ng-value="{{day}}" ng-repeat="day in days" ng-click="hideDayFlag()">{{day}}</ion-radio>
</div>
Controller
$scope.days = [1, 2, 3, 4, 5, 6, 7];
$scope.showDays = function() {
$scope.daysflag = true;
}
$scope.hideDayFlag = function() {
$scope.daysflag = false;
}
Directive
.directive('focusOn',function($timeout) {
return {
restrict : 'A',
link : function($scope,$element,$attr) {
$scope.$watch($attr.focusOn,function(_focusVal) {
$timeout(function() {
_focusVal ? $element[0].focus() :
$element[0].blur();
});
});
}
}
});
Please help me to solve this issue.
You are wrong to use the function scope.$watch. scope.$watch is used to track changes in the $scope.
See detail explanation.
Example on jsfiddle.
angular.module('ExampleApp', [])
.controller('ExampleController', function() {
var vm = this;
vm.isFocus = false;
})
.directive('focusOn', function() {
return {
restrict: 'A',
scope: {
focusOn: "="
},
link: function(scope, $element, $attr) {
scope.$watch('focusOn', function(_focusVal) {
_focusVal ? $element[0].focus() :
$element[0].blur();
});
$element.on("focus", function() {
scope.$applyAsync(function() {
scope.focusOn = true;
});
});
$element.on("blur", function() {
scope.$applyAsync(function() {
scope.focusOn = false;
});
})
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleController as vm">
<input ng-model="vm.countRow" focus-on="vm.isFocus">
<input type="button" value="Focus" ng-click="vm.isFocus=true">
<input type="button" value="Blur" ng-click="vm.isFocus=false">{{vm.isFocus}}
</div>
</div>

Meteor - preventDefault not preventing default

I'm busy with David Turnbull's - Your first Meteor Application. Everything works up to the point where I try and add a new player to the list via a form. My problem is that preventDefault is not preventing the form from trying to submit and reloading the page. return false doesn't work either.
Any ideas why this will be happening?
Thanks
PlayersList = new Mongo.Collection('players');
if (Meteor.isClient) {
//Helpers
Template.leaderboard.helpers({
'player': function() {
return PlayersList.find({}, {sort: {score: -1, name: 1}});
},
'playerCount': function() {
return PlayersList.find().count();
},
'selectedClass': function() {
var playerId = this._id;
var selectedPlayer = Session.get('selectedPlayer');
if(playerId == selectedPlayer) {
return 'selected'
}
},
'showSelectedPlayer': function() {
var selectedPlayer = Session.get('selectedPlayer');
return PlayersList.findOne(selectedPlayer);
}
});
//Events
Template.leaderboard.events({
'click .player': function() {
var playerId = this._id;
Session.set('selectedPlayer', playerId);
},
'click .increment': function() {
var selectedPlayer = Session.get('selectedPlayer');
var increaseBy = document.getElementById('increase-by').value;
var isNumber = /^\d+$/.test(increaseBy);
if(increaseBy != '' && isNumber) {
PlayersList.update(selectedPlayer, {$inc: {score: +increaseBy}});
}
},
'click .decrement': function() {
var selectedPlayer = Session.get('selectedPlayer');
var decreaseBy = document.getElementById('decrease-by').value;
PlayersList.update(selectedPlayer, {$inc: {score: -decreaseBy}});
},
'submit #new-player': function(event) {
event.preventDefault();
var playerNameVar = event.target.playerName.value;
if(playerNameVar != '') {
PlayersList.insert({
name: playerNameVar,
score:0
});
}
}
});
}
Template
<template name="addPlayerForm">
<div id="add-player" class="reveal-modal" data-reveal>
<a class="close-reveal-modal">×</a>
<h2>Add a player</h2>
<p class="lead">Add another player to the leaderboard</p>
<div class="row">
<div class="small-8 column small-centered">
<form id="new-player">
<div class="row collapse">
<div class="small-8 column">
<input type="text" placeholder="Player name" name="playerName">
</div>
<div class="small-4 column">
<input type="submit" class="button postfix" value="add player">
</div>
</div>
</form>
</div>
</div>
</div>
</template>
I've never read the book, and I don't know what your template looks like, but the problem is likely due to a selector issue.
Maybe try assigning an id to your form and mapping the submit event to that id:
// html file
<Template name="leaderboard">
<form id="new-player">
<input type="text" name="playerName">
<input type="submit" value="Submit">
</form>
</Template>
// js file
Template.leaderboard.events({
'submit #new-player': function(event) {
event.preventDefault();
...
}
});
Edit
Maybe try changing Template.leaderboard.events to Template.addPlayerForm.events.
Ok, I made the same mistake as the poster and I am putting the correct code here:
In html file:
<template name="addPlayerForm">
<form>
<input type="text" name="playerName">
<input type="submit" value="Add Player">
</form>
</template>
In js file:
Template.addPlayerForm.events({
'submit form': function(event){
event.preventDefault();
console.log("Form submitted");
console.log(event.type);
}
});

Why doesn't this simple Knockout.js example work?

I am playing around with Knockout.js and created this simple example: http://jsfiddle.net/JcTxT/30/
<div id="term_grp" data-role="fieldcontain"><a>Semester:</a>
<fieldset id="term_fields" data-role="controlgroup" data-type="horizontal">
<input type="radio" name="term" id="ss" value="ss" data-bind="checked: term" />
<label for="ss">Sommersemester</label>
<input type="radio" name="term" id="ws" value="ws" data-bind="checked: term" />
<label for="ws">Wintersemester</label>
</fieldset>
Term is <span data-bind="text: pommes"></span>
var aResult = {
term: ko.observable("ss"),
pommes: "TEST"
};
$(document).on('pagebeforeshow', '#mainPage', function () {
ko.applyBindings(aResult);
});
I expected one of the radio button to be checked (the one with the value "ss" but this is not the case. Does anyone know, why?
Cheers
It works, if you use:
$(function () {
ko.applyBindings(aResult);
});
And turn off jquery mobile.
I tried in your jsfiddle.
If you need jquery mobile, this link works:
http://www.codesizzle.com/jquery-mobile-radio-with-knockout-js/
OK, what needs to be done?
Add another event handler and add it to the binding:
var aResult = {
term: ko.observable("ws"),
pommes: "TEST2"
};
ko.bindingHandlers.mobileradio = {
init: function (element, valueAccessor) {},
update: function (element, valueAccessor) {
var value = valueAccessor();
var valueUnwrapped = ko.utils.unwrapObservable(value);
if (valueUnwrapped == $(element).val()) {
$(element).prop("checked", "true").checkboxradio("refresh");
} else {
$(element).removeProp("checked").checkboxradio("refresh");
}
}
};
$(function () {
ko.applyBindings(aResult);
});
Working fiddle: http://jsfiddle.net/JcTxT/35/

Categories

Resources