Knockout .js and changing values on click - javascript

Simplified code below. I have another build w/ajax calls that I know are working b/c I can see them hit the server. But I cannot get the stuff to render the changes back to the UI.
.html:
<div id="LoginPage" data-title="LoginPage" data-role="page" data-theme="a">
<div data-role="content" class="minimalPaddingContent">
<div class="divDivider"></div>
<h3>REACH Energy Audit Login</h3>
<input type="text" placeholder="User Name" id="userName" data-bind="value: successOrFailureSw"/>
<input type="password" placeholder="Password" id="password"/>
Sign In
<span data-bind="text: successOrFailureSw"></span>
</div>
.js:
var LoginViewModel = function (commonName, successOrFailureSw) {
var self = this;
self.commonName = ko.observable(commonName);
self.successOrFailureSw = ko.observable(successOrFailureSw);
self.changeValue = function(){
console.log("changed!");
self.successOrFailureSw = "new value!";
}
};
ko.applyBindings(new LoginViewModel("", "super fail"));
I am pretty sure my mappings are correct on the .html b/c the original value will render as super fail, and if I change the value in the text box that maps to "successOrFailureSw", I get the updated value in the span tag, but I cannot get a change of effect at click time for the login button.
I know that I am missing something so simple, so I apologize in advance.
Thanks!
brian

You assign value to the observable in wrong way. Each obserbable is a function so you should call it using () modify your changeValue function to the following:
self.changeValue = function(){
console.log("changed!");
self.successOrFailureSw("new value!");
}

You should set the value like this:
self.successOrFailureSw('new value!');
successOrFailureSw is not a string. That's why you need to set it in the same fashion that you did earlier in your code.

Try this :
self.successOrFailureSw("new value!")

Related

Assign dynamic value to an Input Field in HTML

I have an input field and I want to assign it a value dynamically fetched from DB. I will use that value later in a script. Here is my code below
<div data-ng-model="DashboardCounterItems">
<div data-ng-repeat="cItem in DashboardCounterItems">
<input type ="hidden" id ="myInput" value = {{cItem.dbMeetings.length}} />
</div>
</div>
Here {{cItem.dbMeetings.length}} is fetched from DB and assigned to myInput. Further when I check the value of this input in alert in script below, I get {{cItem.dbMeetings.length}} message instead of the value within it.
<script>
var iLenthv = document.getElementById("myInput").value;
alert(iLenthv);
</script>
Any help how can I do it. Or any other better way. I will really appreciate it.
I think your JS code will execute before DB data retrieval, can you check JS code within the setTimeout() Method?
<script>
setTimeout(function() {
var iLenthv = document.getElementById("myInput").getAttribute("value");
alert(iLenthv);
}, 3000);
</script>
Use .getAttribute() to get the value from a html attribute
function myFunction() {
var iLenthv = document.getElementById("myInput").getAttribute("value");
alert(iLenthv);
}
Hope it's helpfull
So we have to track the client side actual value, after the document is loaded. Would you adapt this piece of code and take a look at the console ?
<div data-ng-model="DashboardCounterItems">
<div data-ng-repeat="cItem in DashboardCounterItems">
<input type="hidden" id="myInput" value={{cItem.dbMeetings.length}} />
</div>
</div>
<script>
const test = () => {
var iLenthv = document.getElementById("myInput").value;
console.log("value:",iLenthv);
};
window.onload = test;
</script>

Bind a new function to various elements on a page

This might be a dupe, but I couldn't find exactly what I was looking for. What I want is to bind a function to a named-class element on a page, then in later script, call a function against those regions. Specifically, I want to call something like (in the example below)...
$.each( $(".saveRegion"), function( idx, ele ){
var valsToSave = $(ele).getValuesToSave();
// shove the values to save into some construct
// but only for the controls inside the two divs classed as "saveRegion"
});
My page is a set of conditional includes in the Pug file. The reason that's important, is that the individual page includes might not have the same sets of controls, but that region, or parent div's children nodes, are considered a set of information. Think of a form with address information that might be a region, and gender, eye color, and height that might be a region, all included as separate Pug files if the form in question needs that information. The parent page just wants to ask all the regions "give me your information so I can compile and save it", and each of those includes should be able to respond to that.
I'm probably overdoing it, huh?
div.sampleRegions
if user.height == "tall"
include ./userTall.pug
if user.something == "another value"
include .anotherPage.pug
if user.hair == "brown"
include ./userBrownHair.pug
The html in question might look like:
<div id="sampleRegions">
<div class="saveRegion">
<input class="form-control" id="txtUserName" type="text">
<input class="form-control" id="txtPhone" type="text">
</div>
<div>
<input class="form-control" id="favoriteColor" type="text">
</div>
<div class="saveRegion">
<input class="form-control" id="txtCountry" type="text">
<input class="form-control" id="txtLanguage" type="text">
</div>
</div>
So, I want to bind a function like getValuesToSave() to a div, then write the specifics for that div's getValuesToSave() function. I'm using Pug (formerly Jade) to draw forms based on certain user-specific settings, so the page includes I'm using can each know how to get and return the data for their specific page sections via some prototypical function. I hope this is making sense.
This would be a simple matter of an abstract class or a function override in any other language that supports it. I wrote C# server side stuff for systems processing for like 15 years, and this is trivial there. I am sure I'm just missing something super simple. Thanks!
You are able to use jQuery plugins for this purpose.
Example is available here.
You could go with a simple function which looks for all kind of input elements inside a specified elements and maps their values to objects of type { [nameByAttribute]: value }.
Like this:
function getValues(selector, keyAttr) {
var INPUTS = ['textarea', 'input', 'select'].join();
var BOOL_INPUTS = ['checkbox', 'radio'];
var NUMBER_INPUTS = ['range', 'number'];
var regions = [].slice.call(document.querySelectorAll(selector));
return regions.map(function(region) {
var values = [].slice.call(region.querySelectorAll(INPUTS));
return values.map(function(element, index) {
var type = element.getAttribute('type');
var key = element.getAttribute(keyAttr) || index;
var value = element.value;
if(BOOL_INPUTS.indexOf(type) > -1) value = element.checked;
if(NUMBER_INPUTS.indexOf(type) > -1) value = +element.value;
return { [key]: value };
});
});
}
document.querySelector('#save').addEventListener('click', function() {
console.log(getValues('.saveRegion', 'id'));
});
<div id="sampleRegions">
<div class="saveRegion">
<input class="form-control" id="txtUserName" type="radio">
<input class="form-control" id="txtPhone" type="checkbox">
<input class="form-control" id="txtPhone" type="range">
<select idd="language">
<option>EN</option>
<option>DE</option>
<option>FR</option>
</select>
</div>
<div>
<input class="form-control" id="favoriteColor" type="text">
</div>
<div class="saveRegion">
<input class="form-control" id="txtCountry" type="text" value="textInput">
<textarea class="form-control" id="txtLanguage">textArea</textarea>
</div>
<button id="save">save</button>
</div>
This could be easily extended to take a mapping as input, which defines how certain inputs should be handled.
Ok, I think what I'm going to do is just add a function to each of the include pages that knows how to return an object containing the values for that region's salient controls, and name it based on the region name or something else to ensure uniqueness. Something like:
In Include-page-1
<div class="saveRegion" saveFunc="saveNameAddressRegion()">
<input id="val1" ..../>
<input id="val2" ..../>
<input..../>
</div>
<script>
function saveNameAddressRegion(){
// stupid-simple example
return { val1: $("#val1").val(), val2 : $("#val2").val() };
}
</script>
Or in Jade/Pug template:
.saveRegion(saveFunc="saveNameAddressRegion()")
input#val1(type="text")
input#val2(type="text")
input#val3(type="text")
script.
function saveNameAddressRegion(){
// stupid-simple example
return { val1: $("#val1").val(), val2 : $("#val2").val() };
}
Then in Include-page-2
<div class="saveRegion" saveFunc="doItAgain()">
<select id="selEyeColor">
<option value="blue">Blue</option>
<option value="green">Green</option>
<option value="brown">Brown</option>
</select>
</div>
<script>
function doItAgain(){
return { eyeColor : $("#selEyeColor option:selected").val() };
}
</script>
And then the enclosing/parent page can just do something like:
include ./Include-Page-1.pug
include ./Include-Page-2.pug
script.
$.each(".saveRegion", function( idx, ele ){
var vals = [];
vals.push( eval( $(ele).attr("saveFunc") ) );
// process them or whatever here.
});
This lets me get to a point where each Include file has a way of returning its values that may or may not be in some complicated on-screen form, control layout, etc. The parent page can always expect a simplified object with values, without knowing anything at all about each of the include-page layouts, design, contents, etc.
(( shrug ))

angular-tags: Reset the tags input value

index.html
<div class="modal-header" >
<button type="button" class="close" ng-click = "submit(information.add, information.subject, information.emailContent); close()">×</button>
<h3>Compose Email</h3>
</div>
<div class="modal-body">
<form name = "form.email">
<tags options="{addable: true}" typeahead-options="typeaheadOpts" data-model="information.add" data-src="toPerson as toPerson for toPerson in to"></tags>
<input type="text" placeholder="Subject" style="width:95%;" data-ng-model = "information.subject"><br />
<textarea style="width:95%;" rows="10" data-ng-model = "information.emailContent"></textarea>
</form>
</div>
emailViewController.js
$scope.information = {
add: [],
subject: [],
emailContent: []
};
$scope.clear = function() {
if ($scope.information.add !== "") {
$scope.information = null;
}
};
I am setting the value of $scope.information to null. After doing this, the input box value bound to information.subject and the textarea value bound to information.emailContent are reset. However, the tags input value bound to information.add does not reset. Does anyone know why this is being caused.
I think $scope.remove() in the angular-tags widget should be used to remove the tag. I am not sure how to implement it though. Angular-tags source code can be found here - https://github.com/boneskull/angular-tags/blob/master/src/tags.js
Here is a plunker - http://plnkr.co/edit/PaG1k5N37BTOflObnN7K?p=preview
Attempt 1
This is a plunker of what I have tried so far - http://plnkr.co/edit/jjE2bU8zkkyw36rtAymL?p=preview . I am redefining the value of $scope.info to null in a function wrapped inside $timeout. I thought maybe the changes I made to the $scope are not being applied to the view, so I tried to wrap it in a $timeout. Doing so did not fix the problem though.
This code $scope.information = null; is supposed to nuke all your information and clear the entire thing? This only sets the reference to the object containing the arrays to null. The arrays are still there and still referenced by your widget I expect - (I'm not sure how the library you are using for your tags is implemented)
The below code actually empties the arrays:
$scope.information.add.length = 0;
$scope.information.subject.length = 0;
$scope.information.emailContent.length = 0;

Passing the value of a button into a text field

I'm having some trouble with getting Javascript to pass a value (which is stored in local storage) into a textfield. Ideally, I'd like for someone to be able to click the 'apply here' button on one page, have the job number stored in local storage and then have it auto-populate the job number field on my application page with the job number.
This is what I've got so far, I have a feeling that I haven't assigned things correctly.
html (on submit page)
<p>
<form id="applyjob1" action="enquire.html" method="get">
<input type="submit" id="job1" value="Apply for Job" />
</form>
</p>
html (field I'm trying to put data into)
Job Reference Number <input required="required" id="jobNo" name="jobno" type="text" /> </br />
Javascript
window.onload = function init() {
var jobID = document.getElementById("job"); /*button name */
jobID.onsubmit = passJob; /*executes passJob function */
}
function passJob(){
var jobSubmit = localstorage.jobID("1984"); /*assigns localstorage*/
if (jobSubmit != undefined){
document.getElementById("jobNo").value = localstorage.jobID;
}
I think this code would work for your fuction.
function passJob(){
localStorage.setItem("jobID", "1984");
if (localStorage.jobID != undefined) {
document.getElementById("jobNo").value = localStorage.jobID;
}
}
You are assigning the jobSubmit wrongly. To set item, use localStorage.setItem('key', value). Note the casing as it matters.
So basically you should do
var jobSubmit = localStorage.setItem(,"jobID", "1984"); // assigns jobSubmit
And I don't see any element with id="job"

AngularJS display alert depending on input value

I am coding a CRUD application in Angular and Web API.
In the create/edit form (same template), I need to display an error message if 2 input fields don't have the same number of comma ','.
I found a way to make it work but I don't like it, I think it needs to be "angularized" but I don't know how.
Controller:
$scope.isColumnCountOk = true;
$scope.checkColumnCountOk = function () { $scope.isColumnCountOk = AdminUtils.isColumnCountOk($scope.item.columnSqlNames, $scope.item.columnTitles) };
Template:
<input type="text" class="form-control" ng-model="item.columnTitles" placeholder="Report Column 1,Report Column 2,Report Column 3,..." ng-blur="checkColumnCountOk()" required />
<div ng-hide="isColumnCountOk">
<br />
<div class="alert alert-danger" ><strong>Warning. </strong>Mismatch between column numbers</div>
</div>
I would like to get rid of the $scope.isColumnCountOk and have the function called directly from the template, without storing the return value in the scope.
Any advice?
Bruno
I think both of these ways should work...
$scope.isColumnCountOk = function () {
return AdminUtils.isColumnCountOk($scope.item.columnSqlNames, $scope.item.columnTitles);
};
<div ng-hide="isColumnCountOk()">
...
</div>
Or
$scope.isColumnCountOk = AdminUtils.isColumnCountOk;
<div ng-hide="isColumnCountOk(item.columnSqlNames, item.columnTitles)">
...
</div>

Categories