Knockout JS `hasFocus` within template that is called twice - javascript

I have a template, which is using hasFocus similar to example in docs: http://knockoutjs.com/documentation/hasfocus-binding.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>field test</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css">
<style>
body {
margin-top: 1em;
}
</style>
<script src="https://cdn.jsdelivr.net/g/jquery#2.2.2,bootstrap#3.3.6,knockout#3.4.0"></script>
<script>
$(function() {
var VM = function() {
var model = {};
model = {
one: ko.observable(false),
two: ko.observable(false)
};
this.model = model;
};
ko.applyBindings(new VM());
});
</script>
</head>
<body>
<script type="text/template" id="first-template">
<input type="text" class='form-control' data-bind="hasFocus: model.one">
<p>one has<span data-bind="visible: !model.one()"> not got</span> focus now</p>
<input type="text" class='form-control' data-bind="hasFocus: model.two">
<p>two has<span data-bind="visible: !model.two()"> not got</span> focus now</p>
</script>
<div class="container">
<div class="row">
<div class="col-sm-12">
<div data-bind="template: { name: 'first-template' }"></div>
<!-- if I uncomment the next line, it stops working... -->
<!-- <div data-bind="template: { name: 'first-template' }"></div> -->
</div>
</div>
</div>
</body>
</html>
It all works as expected, updating the focus state on the model correctly when entering and leaving the field. However, if I apply the template a second time, the template appears to work ok with the exception of the focus state. Is this unsupported, or am I implementing wrong? How can I use template multiple times, and still use focus state?

The browser cannot have two <input> elements with focus. The hasFocus bind will try to give both elements a focused state. You can circumvent this behavior by using event bindings for both focus and blur events:
data-bind="event: {
focus: function() {
model.one(true)
},
blur: function() {
model.one(false)
}
}"
Check out this fiddle for a working example of your code: https://jsfiddle.net/77meefmf/

You need to make sure each copy of the template has its own viewmodel. The hasFocus binding is meant to represent the focus status a single field. If you bind it to more then one field, the results will be wrong.

Related

kendo ui on-demand RTL support with script

I created an Autocomplete form. I followed this simple documentation to create a button together with its click handler script. Clicking this button shall toggle RTL support for the form.
I have a problem. When I click the button, it does not toggle RTL support for the form.
demo
<body>
<input type="button" id="toggleRTL" value="Activate RTL Support" class="k-button" />
<script>
$('#toggleRTL').on('click', function(event) {
var form = $('#speakerForm');
if (form.hasClass('k-rtl')) {
form.removeClass('k-rtl')
} else {
form.addClass('k-rtl');
}
})
</script>
<input id="autocomplete" type="text" />
<script>
$("#autocomplete").kendoAutoComplete({
dataSource: {
data: [
{name: "Google"},
{name: "Bing"}
]
},
dataTextField: "name",
})
</script>
</body>
I think you missing some point from the tutorial :
you need to put all of your component to a container element and apply the k-rtl class to the container
you have a problem on your js where you dont have element with id speakerForm
UPDATE
3. as your comment i, i observe the behavior of the k-rtl and kendo autocomplete widget and the result is the suggestion will be still on the left side if we create the widget first then adding the k-rtl clas. So what do we need is the container having the k-rtl class first then initializing the widget.
4. i updated my code so that every time you click the button the #autocomplete div will be removed with its parent( result from kendo autocomplete which is a span) then append new element and re-initializing the kendo autocompelete widget
I think it's working if you follow it like this
function createAutoComplete(){
if($("#autocomplete").data("kendoAutoComplete") != null){
$("#autocomplete").parent().remove();
$("#container").append("<input id='autocomplete' type='text' />")
}
$("#autocomplete").kendoAutoComplete({
dataSource: {
data: [{
name: "Google"
}, {
name: "Bing"
}]
},
dataTextField: "name",
});
}
createAutoComplete();
$('#toggleRTL').on('click', function(event) {
var form = $('#container');
console.log(form);
if (form.hasClass('k-rtl')) {
console.log("test1");
form.removeClass('k-rtl')
} else {
console.log("test2");
form.addClass('k-rtl');
}
createAutoComplete();
})
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Untitled</title>
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.common.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.rtl.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://kendo.cdn.telerik.com/2015.3.930/styles/kendo.mobile.all.min.css">
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/angular.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/jszip.min.js"></script>
<script src="http://kendo.cdn.telerik.com/2015.3.930/js/kendo.all.min.js"></script>
</head>
<body>
<div id="container">
<input type="button" id="toggleRTL" value="Activate RTL Support" class="k-button" />
<input id="autocomplete" type="text" />
</div>
</body>
</html>
I have updated your dojo.
http://dojo.telerik.com/AfeNi/4
But as #machun has stated you are missing some elements of the mechanics of this process.
I have added the missing form element speakerForm and then added some additional console.log() statements showing the actions being performed.
if you need any more info let me know.

Angular not picking up changed input value

Javascript noob here :)
I have a basic Angular web page that adds input to a list when the "add" (submit) button is clicked. If, however, I submit by pressing the ENTER key, Angular does not recognise that the input field is dirty, and it fails to update the model ($scope.newFundName) - so the old value (initially "") is added to the list. If I move focus away from the field and back again (say TAB, then BACKTAB) then Angular picks up the correct value. How do I force it to use the current value of the input field without manually shifting the focus?
My code:
<!doctype html>
<html ng-app> <!-- test004.html -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script src="../angular-1.0.0rc3.min.js"></script>
<script type="text/javascript">
function testController004($scope) {
$scope.funds = [{code:1 ,name:'Alpha'}
,{code:2 ,name:'Bravo'}
,{code:3 ,name:'Charlie'}];
$scope.getFundCount = function () { return $scope.funds.length; }
$scope.addFund = function () {
// if triggered by ENTER, and focus hasn't left a dirty input field, new value won't be picked up
$scope.funds.push({code:$scope.newFundCode,name:$scope.newFundName});
}
}
</script>
</head>
<body>
<div ng-controller="testController004" class="container">
<label># Funds: {{getFundCount()}}</label>
<ul>
<li ng-repeat="F in funds">
<span>{{F.code}}={{F.name}}</span>
</li>
</ul>
<form role="form" class="form-inline">
<label for="eFundCode">Code</label>
<input id="eFundCode" type="text" class="form-control" ng-model="newFundCode" />
<label for="eFundName">Name</label>
<input id="eFundName" type="text" class="form-control" ng-model="newFundName" />
<button id="eAdd" class="btn btn-info" ng-click="addFund()">Add</button>
</form>
</div>
</body>
</html>

How to access refreshView() in Twitter Bootstrap Datepicker for Angular?

EDIT It actually does it right out of the box.
I leave the plunker here just in case someone drops in via search: http://plnkr.co/edit/maArVIu6iWuWZbkvLI4j?p=preview
I need to disable disable specific dates in a datepicker based on user input.
The datepicker offers isDisabled(date) but that only gets fired once. It does however have a refreshView() as per: https://github.com/angular-ui/bootstrap/issues/779
What I can't figure out is how to trigger it after a change.
<!doctype html>
<html ng-app="plunker">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
<script src="example.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="DatepickerDemoCtrl" >
<h4>Inline</h4>
<div style="display:inline-block; min-height:290px;">
<div class="well well-sm" ng-model="dt" ng-change="change()">
<datepicker></datepicker>
</div>
</div>
</div>
</body>
</html>
and the js
angular.module('plunker', ['ui.bootstrap']);
var DatepickerDemoCtrl = function ($scope) {
$scope.change = function(){
console.log('changed to ' + $scope.dt);
// Get array of disabled dates
// call refreshView(); <--- My problem, right here
};
};
I've ommitted the part where I define an array of disabled dates and the isDisabled function that checks against that. What I only need to know is how to trigger the refreshView()
EDIT:
This is what I want to call/trigger in ui-bootstrap-tpls.js
this.refreshView = function() {
if ( this.element ) {
this._refreshView();
var date = ngModelCtrl.$modelValue ? new Date(ngModelCtrl.$modelValue) : null;
ngModelCtrl.$setValidity('date-disabled', !date || (this.element && !this.isDisabled(date)));
}
};

Angularjs templating: model and function stop working in external templates?

After this question, I am facing another challenge, the model and function inside the $scope seem have stopped working. Below is the test code, the Add button seem does not collect any data I input from <input type='text' ng-model='newPerson' /> anymore,
html,
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>AngularJS</title>
<meta charset="utf-8">
<script src="js/jquery-1.10.1.min.js"></script>
<script src="js/angular.min.js"></script>
<script src="js/app.js" type="text/javascript"></script>
</head>
<body>
<div ng-app='MyTutorialApp' ng-controller='MainController'>
<div ng-include='thisIsAScopeProperty'></div>
</div>
</body>
</html>
the external template,
<div id='content'>
<input type='text' ng-model='searchText' />
<ul>
<li ng-repeat='person in people | filter:searchText' ng-show='person.live == true'>#{{person.id}} {{person.name}}</li>
</ul>
<input type='text' ng-model='newPerson' />
<button ng-click='addNew()'>Add</button>
</div>
angularjs,
var app = angular.module('MyTutorialApp',[]);
app.controller("MainController", function($scope){
$scope.thisIsAScopeProperty = 'template/index.html';
$scope.people = [
{
id: 0,
name: 'Leon',
music: [
'Rock',
'Metal',
'Dubstep',
'Electro'
],
live: true
}
];
$scope.newPerson = null;
$scope.addNew = function() {
alert(1); // works here when you click the Add button
console.log($scope.newPerson); // but returns nothing when you type any text in the input
if ($scope.newPerson != null && $scope.newPerson != "") {
alert(2); // does not work here
$scope.people.push({
id: $scope.people.length,
name: $scope.newPerson,
live: true,
music: [
'Pop',
'RnB',
'Hip Hop'
]
});
}
}
});
Any ideas why and how can I fix it?
Use
<input type='text' ng-model='$parent.newPerson' />
ng-include creates a new scope, and because newPerson is a simple property, it's a different one on the child and parent scopes (i.e. changing one doesn't change the other). So when the included template sets newPerson it's still null on the mainController's scope.
For a better understanding of how scopes work, read https://github.com/angular/angular.js/wiki/Understanding-Scopes

Rich Text Editor (YUI Simple Text Editor used) not sending data to next page

I am using a simple text editor from YUI, but when I click submit the code in the textarea/editor is not sent to the next page. I want to be able to receive it on the subsequent page and then store it in a DB(MySql). I have wasted lot of time already. Please help.
HTML FILE:
<html>
<head>
<script type="text/javascript" src="http://yui.yahooapis.com/combo?2.9.0/build/yahoo-dom-event/yahoo-dom-event.js&2.9.0/build/container/container_core-min.js&2.9.0/build/element/element-min.js&2.9.0/build/editor/simpleeditor-min.js"></script>
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.9.0/build/editor/assets/skins/sam/simpleeditor.css" />
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/2.8.2r1/build/assets/skins/sam/skin.css">
<!-- Utility Dependencies -->
<script src="http://yui.yahooapis.com/2.8.2r1/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script src="http://yui.yahooapis.com/2.8.2r1/build/element/element-min.js"></script>
<!-- Needed for Menus, Buttons and Overlays used in the Toolbar -->
<script src="http://yui.yahooapis.com/2.8.2r1/build/container/container_core-min.js"></script>
<script src="http://yui.yahooapis.com/2.8.2r1/build/menu/menu-min.js"></script>
<script src="http://yui.yahooapis.com/2.8.2r1/build/button/button-min.js"></script>
<!-- Source file for Rich Text Editor-->
<script src="http://yui.yahooapis.com/2.8.2r1/build/editor/editor-min.js"></script>
<script>
YAHOO.util.Event.on('submit', 'click', function() {
myEditor.saveHTML();
var html = myEditor.get('element').value;
});
(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event;
var myConfig = {
height: '200px',
width: '900px',
dompath: true,
};
myEditor = new YAHOO.widget.SimpleEditor('msgpost', myConfig);
myEditor.render();
})();
</script>
</head>
<body class="yui-skin-sam">
<form action="submit.php" method="post">
<textarea name="msgpost" id="msgpost" cols="50" rows="10"></textarea>
<input type="submit" value="Submit" onsubmit="return myDoSubmit()"/>
</form>
</body>
</html>
The saveHTML() method you used does not seem to save the value to the textarea element. And because the browser doesn't care about YUI Editor and just submits what is there already in the textarea (which is null), it submits the input as null..
You should set the value of the textarea to the editor value so the browser will submit that value instead of null.. Which can be achieved using this little line:
document.getElementsById("msgpost").value = html;
See this working JsFiddle I made for you.
However you had HTML syntax errors too. The onSubmit attribute should be on the form element not the submit button.
And listening to the event is not practical when you can simply call a function when the form submits.. (See the JsFiddle)
I saw an example on this post.
Basically, add this to myConfig: handleSubmit: true
myConfig will then look like this:
var myConfig = {
height: '200px',
width: '900px',
dompath: true,
handleSubmit: true
};

Categories

Resources