HTML "this" versus AngularJS ng-model - html

We are in the process of converting a very old ColdFusion application that made convenient use of "this" in conjunction with a function that did formatting:
<td>$<input type="text" name="txtTaxProration" id="txtTaxProration" value="0.00" alt="Tax Proration" onblur="dollarBlur(this);"></td>
The dollarBlur function would convert the numeric input to currency, i.e if the user entered 123, it was converted to 123.00; 23.45 was left as 23.45. This made the reference on the HTML side easy, but even easier in the actual function as the name of the element did not have to be specified. Is there some analogous way to do this in Angular?
<td>$<input type="text" ng-model="NetSheetDetail.TxtHomeWarranty" name="txtHomeWarrantyPolicy" id="txtHomeWarrantyPolicy" value="0.00" ng-change="angularDollarBlur(this)" ng-model-options="{ updateOn: 'blur' }"></td>
The following works fine, almost, HTML
<input type="text" ng-model="NetSheetDetail.TxtHomeWarranty" ng-change="reCalcX('NetSheetDetail.TxtHomeWarranty')" ng-model-options="{ updateOn: 'blur' }" ></td>
Controller
$scope.reCalcX = function (propName) {
alert($scope.$eval(propName));
$scope['propName'] = 666;
};
$scope.$eval(propName) does correctly reflect what was entered on the webpage ($scope['propName'] is undefined). However, $scope['propName'] doesn't appear to work - the change is not reflected back in the webpage.

Yes, simply pass the model.
ng-change="angularDollarBlur(NetSheetDetail.TxtHomeWarranty)"
$scope.angularDollarBlur = function (model) {
console.log(model);
}
Here's another example:
angular.module('app',[]).controller('myController', function ($scope) {
$scope.NetSheetDetail = {
TxtHomeWarranty: 'Hello World!'
};
$scope.angularDollarBlur = function (text, obj, prop) {
alert(text);
obj[prop] = 'Nope.';
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="myController">
<input type="text" ng-model="NetSheetDetail.TxtHomeWarranty" ng-change="angularDollarBlur(NetSheetDetail.TxtHomeWarranty,NetSheetDetail,'TxtHomeWarranty')" />
</div>

Related

Concat Form Field Values

Hopefully I'm not repeating this question in anyways. But I am trying to get a form section with its name values and field vales to put as a single concat string. So like
Form Input:
First Name: John
Last Name: Smith
Fields 5 - 10.. etc
String Output:
FirstName=John&LastName=Smith&Field2=Value2&Field_etc=Value_etc
I tried
var inputArray = $("form#form :input").each(function () {
var input = $(this);
console.log(input.attr('name') + ":" + input.val());
});
Which outputs a test value correctly in the console.log as
firstName:John
lastName:Smith
but I'm struggling on the next bit of code that will help console.log it as a combine array string. Not sure if this is a for loop or something that helps the next step.
See comments in code below, maybe this might help you get on the right track...
The main cool thing here is to store submission data as an object and then use $.param() to convert submission to url string.
// on form submit
$(document).on('submit', '#form', function(e) {
// prevent form default submit action
e.preventDefault();
// set empty submission object
let submission = {};
// for each of this form submit event target object entries as key/field
for (const [key, field] of Object.entries(e.target)) {
// if object entry (field) has a name attribute
if (field.name) {
// add name/value to submission object
submission[field.name] = field.value;
}
}
// convert submission object to url params string
var paramsStr = $.param( submission );
// log the string
console.log(paramsStr)
});
<form id="form">
<input name="firstName" value="John" type="text" />
<input name="lastName" value="Smith" type="text" />
<input name="userName" value="johnsmith" type="text" />
<button type="submit">Submit</button>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Loop through the input elements and concatenate the name and value:
const inputs = document.querySelectorAll('#form input')
let msg
inputs.forEach(inp => {
inp.onkeyup = () => {
msg = 'String Output: '
inputs.forEach(i => msg += `${i.name}=${i.value}&`)
console.clear()
console.log(`\r\n${msg.slice(0, -1)}\r\n\r\n`)
}
})
input {
display: block;
margin-bottom: 8px;
font:18px/1.2em Arial;
}
<form id='form'>
<input name='FirstName' placeholder='First Name' />
<input name='LastName' placeholder='Last Name' />
<input name='Example1' placeholder='Example 1' />
<input name='Example2' placeholder='Example 2' />
</form>

Refresh SlickGrid via call to JsonResult after initial load

I have setup a MVC webpage with a SlickGrid and can populate it upon initial page load. My javascript for loading:
$.getJSON("../Home/GetSlickGridData",
function(data) {
dataView.beginUpdate();
//dataView.setItems(data);
dataView.setItems(data, "OrderID");
dataView.setFilterArgs({
searchString: searchString,
searchShipmentID: searchShipmentID,
searchDestination: searchDestination,
searchCarrier: searchCarrier
});
dataView.setFilter(myFilter);
dataView.endUpdate();
});
This calls a controller action:
public JsonResult GetSlickGridData()
{
The issue now is that I'm unsure of how to refresh the grid when a search criteria is added to the cshtml page's search form:
#using (Html.BeginForm("GetSlickGridData", "Home"))
{
<table>
<tr>
<td>Shipper</td>
<td><input type="text" name="myText" id="txtShipper" /></td>
<td><input type="submit" value="Filter" onclick="GetData"></td>
</tr>
</table>
}
Can I use the loading for initial page load and for a search?
UPDATE:
Based on #Steve T's answer:
The search:
> <input type="text" name="myText" id="txtShipper" />
> <input type="button" value="Filter" onclick="GetData()">
The jquery:
function GetData() {
Slick.GlobalEditorLock.cancelCurrentEdit();
grid.invalidateAllRows();
var searchText = $("#txtShipper").val();
$.getJSON("../Home/GetSlickGridData?search=" + searchText,
function (data) {
The controller:
public JsonResult GetSlickGridData(string search)
And the map route (to ensure the controller works):
routes.MapRoute("search", "Home/GetSlickGridData/{search}",
new {Controller = "Home", Action = "GetSlickGridData"});
Instead of submitting the form and reloading the whole page you can change the filter button to type="button" and then use the GetData() function (not sure if you have this already implemented) to repeat the initial $.getJSON call with the value of text field txtShipper as a parameter

How to convert text to uppercase while typing in input field using angular js

I know that is posible with jquery but I dont know how to do that with angular js, please any sugestion?
function mayuscula(campo){
$(campo).keyup(function() {
$(this).val($(this).val().toUpperCase());
});
}
You can also create a directive for this!
Check the code:
directive('uppercase', function() {
return {
restrict: "A"
require: "?ngModel",
link: function(scope, element, attrs, ngModel) {
//This part of the code manipulates the model
ngModel.$parsers.push(function(input) {
return input ? input.toUpperCase() : "";
});
//This part of the code manipulates the viewvalue of the element
element.css("text-transform","uppercase");
}
};
})
For its usage, here's an example:
<input type="text" ng-model="myModel" uppercase />
You could do it in HTML template or via JS using the angular uppercase filter.
<div>
<label>Input 1</label>
<input type="text" ng-model="first">{{ first | uppercase }}
</div>
If you need to change the value in-place, use toUpperCase when ever value is changed.
<div>
<label>Input 1</label>
<input type="text" ng-model="first" ng-change="text = text.toUpperCase()">
</div>
Above in preferred approaches. Here's yet another way to achieve same result using $watch but this is not recommended. See comments section.
<div>
<label>Input 2</label>
<input type="text" ng-model="second">
</div>
var unwatch = $scope.$watch('second', function(val) {
$scope.second = $filter('uppercase')(val);
}, true);
$scope.$on('$destroy', unwatch);
Related Plunker here http://plnkr.co/edit/susiRn

How to send the input text box value to angularjs onclick on the text box?

Below is my html:
<tr ng-repeat="c in client">
<td><input type =text id = "id" value = {{c.id}} onclick = "display();" > </input> </td>
<td><input type =text value = {{c.fname}}></td>
</tr>
My js:
function display()
{
var x=document.forms["form"]["id"].value;
alert(x);
}
I am getting the input value in the alert box successfully but how to get this value in another angular js function. I tried the below code but not working please suggest me
<input type =text id = "id" value = {{c.id}} ng-model = user.id ng-click ="init(user)" > </input>
If you have set up your application properly, you simply create the init() function in your controller
$scope.init = function (user) {
// function implementation
};
Also make sure you format your HTML correctly
<input type="text" id="id" value="{{c.id}}" ng-model="user" ng-click ="init(user)" />
A much more cleaner way to accomplish the same thing would be to just set the value on the click event for example.
<td onclick="user.id=ID"> </td>

knockout issue with deleting from observable array

I'm having data binding a knockout function to my html.
Following is the view model:
var DonutViewModel = function () {
this.donuts = ko.observableArray();
//donutData = JSON.parse(donutData);
var items = $.map(donutData, function (data) { return new Donut(data) });
this.donuts(items);
this.deletedonut = function (item) {
this.donuts.remove(item);
}
}
var viewModel;
$(document).ready(function () {
viewModel = new DonutViewModel();
ko.applyBindings(viewModel);
});
following is the html:
<tr>
<td><input id="txtdonutid" type="text" data-bind="value:id"/></td>
<td><input id="txtdonuttype" type="text" data-bind="value:type"/></td>
<td><input id="txtdonutname" type="text" data-bind="value:dname"/></td>
<td><input id="txtppu" type="text" data-bind="value:ppu"/></td>
<td><input type="button" value="Delete Donut" data-bind="click: function() {$parent.deletedonut($data)}"/></td>
</tr>
Notice how I have data-bound the delete function and THIS WORKS!. but if I do the following:
<td><input type="button" value="Delete Donut" data-bind="click: {$parent.deletedonut($data)}"/></td>
well, this doesn't work. The delete function doesn't even get hit.
Can someone tell me what I'm doing wrong?
You only need to the function() ... syntax in your click binding if you want to pass additional parameter to your handler beside the $data. (see the documentation: Accessing the event object, or passing more parameters section)
But if your only parameter is $data then KO will automatically pass that in so you can just write:
<input type="button" value="Delete Donut"
data-bind="click: $parent.deletedonut"/>
Note: there is no need for the {} and you also don't need arguments as well ($data) because you are passing the $parent.deletedonut as the reference to that handler function.
But in itself this won't work in your case because you are using this in your handler to access your view model.
You have two options:
You can use bind: data-bind="click: $parent.deletedonut.bind($parent)" in this case you don't need to change your handler.
Demo JSFiddle
Or you can store a reference of the this in a variable like self and use that in your handler instead of the this.
So change your handler to:
var self = this;
this.deletedonut = function (item) {
self.donuts.remove(item);
}
Demo JSFiddle.