I want to change Cloudera Hue project code but I have some problems.
Knockout data-bind is created some html codes with foreach , when I want to reach input in this html, my code does not work correct. My app.mako file code :
.....
<div data-bind="foreach: submissionVariables" style="margin-bottom: 20px">
<div class="row-fluid">
<span data-bind="text: name" class="span3"></span>
<input type="text" data-bind="value: value,attr: { id: 'dtpicker' + name }" class="span9" />
<button class="btn fileChooserBtn" data-bind="click: $root.showTimePicker">time</button>
</div>
</div>
<input type="text" value="2014/03/15 05:06" id="datetimepickerz"/>
....
<script src="/static/js/jquery.datetimepicker.js"></script>
<script type="text/javascript">
$('#dtpickerfolder').datetimepicker()
.datetimepicker({value:'2015/04/15 05:03',step:10});
$('#dtpickereverything').datetimepicker()
.datetimepicker({value:'2015/04/15 05:03',step:10});
$('#datetimepickerz').datetimepicker()
.datetimepicker({value:'2015/04/15 05:03',step:10});
</script>
Output:
<input id="dtpickerfolder" class="span9" type="text" data-bind="value: value,attr: { id: 'dtpicker' + name }"></input>
<input id="dtpickereverything" class="span9" type="text" data-bind="value: value,attr: { id: 'dtpicker' + name }"></input>
<input id="datetimepickerz" type="text" value="2014/03/15 05:06"></input>
datetimepickerz input works correct but my dynamic inputs that ids starts with dtpicker are not working.
Can anyone help me ?
I solve this with :
self.runOrShowSubmissionModal = function runOrShowSubmissionModal() {
var script = self.currentScript();
if (! $.isEmptyObject(script.getParameters())) {
self.submissionVariables.removeAll();
$.each(script.getParameters(), function (key, value) {
self.submissionVariables.push({'name': key, 'value': value});
// CALL TO JQUERY
$("#dtpicker"+key).datetimepicker({value:"2015/04/15 05:03",step:10});
});
$("#runScriptBtn").button("reset");
$("#runScriptBtn").attr("data-loading-text", $("#runScriptBtn").text() + " ...");
$("#submitModal").modal({
keyboard: true,
show: true
});
} else {
self.runScript();
}
};
I sent my jquery in knockout function.
Related
Here is clear exampel about forms:
<div ng-form="namesForm_{{$index}}" ng-repeat="name in names">
<input type="text"
name="input_{{$index}}_0"></input>
<!-- ... -->
Ok, but how I should access $valid field from form? E.g this does not work:
{{namesForm_$index.$valid}}
Even {{namesForm_$index}} outputs 0.
It is need to "inline" $index before {{}} resolve a variable name. How to do that?
It's not easy to get it inside of single {{ }} expression, but if you only want to use it in directives accepting expressions without handlebar (like ng-disabled), you can achieve that:
<div ng-app>
<ng-form name="namesForm_{{$index}}" ng-repeat="name in [1, 2]">
<input type="text"
placeholder="{{$index}}"
ng-required="true"
ng-model="test"
name="hey" />
<button ng-disabled="!namesForm_{{$index}}.$valid">
send
</button>
<br />
</ng-form>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
{{ IsFormValid($index) }}
$scope.IsFormValid = function(index) {
var form = angular.element("formName" + index);
return form.$valid;
};
UPDATED
Working example:
{{ IsFormValid($index) }}
$scope.IsFormValid = function(index) {
var form = angular.element(document.getElementById('#bucketForm-' + index);
return form.$valid;
};
New Approach
The below is an example for dynamic ngModel, same can be replicated for form name :
$scope.formData = {};
$scope.formData = {
settings:
{
apiEndpoint: '',
method: 'get'
},
parameters: {}
};
<div class="form-group" ng-repeat="parameter in apiParameters">
<label for="{{parameter.paramName}}" class="col-sm-2 control-label">{{parameter.paramTitle}}</label>
<div class="col-sm-3">
<input type="text" class="form-control" name="{{parameter.paramName}}" id="{{parameter.paramName}}" ng-model="formData.parameters[parameter.paramName]" placeholder="{{parameter.paramTitle}}">
</div>
</div>
$(document).ready(function () {
jQuery.validator.addMethod("insz", function (value, element) {
var insz = $('#txtINSZ').val()
var controle = parseInt(insz.substring(13, 15))
var getal = insz.substring(0, 2) + insz.substring(3, 5) + insz.substring(6, 8) + insz.substring(9, 12)
var rest = parseInt(getal) % 97
alert("we doin' this mun")
return 97 - rest == controle;
}, "* Amount must be greater than zero");
$('#form1').validate({
rules: {
txtINSZ: {
required: $('#cbInsz').prop('checked') == false,
insz: function () {
$('#cbInsz').prop('checked') == true;
}
}
},
showErrors: function (errorMap, errorList) {
this.defaultShowErrors();// to display the default error placement
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/jquery.validation/1.16.0/jquery.validate.js"></script>
<form method="post" action="#" id="form1" a="" novalidate="novalidate">
<div id="container">
<div class="container-fluid">
<div class="col-xs-12">
<div class="form-horizontal col-xs-4" id="divDimLeft">
<span id="lblTitleAlgemeen">Algemen Informatie</span>
<div class="checkbox" style="margin-left:20px;">
<span id="lblCheck">
<input type="checkbox" id="cbInsz" checked="">
INSZ nummer werknemer gekend?
</span>
</div>
<div class="form-group" id="divINSZ">
<span id="lblINSZ" class="required" for="txtINSZ" aria-required="true">INSZ-nummer gekend?</span>
<input name="ctl00$ContentPlaceHolder1$txtINSZ" type="text" maxlength="15" id="txtINSZ" class="form-control required form valid" oninput="autoInvullen()" aria-required="true" placeholder="__.__.__-___.__" aria-invalid="false" required=""><label id="txtINSZ-error" class="error" for="txtINSZ" style="display: none;"></label>
</div>
<div class="form-group">
<span id="lblNaam" class="required" for="txtNaam" aria-required="true">Naam</span>
<input name="ctl00$ContentPlaceHolder1$txtNaam" type="text" maxlength="40" id="txtNaam" class="form-control form requiredField error" aria-required="true" aria-invalid="true"><label id="txtNaam-error" class="error" for="txtNaam">Dit veld is verplicht.</label>
</div>
<div id="divButton" class="text-right" style="width: 87.5%">
<input type="submit" name="ctl00$ContentPlaceHolder1$btnSubmit" value="Volgende" id="btnSubmit" class="btn btn-primary col-xs-2" style="float: none; min-width:200px;">
</div>
</div>
</div>
</div>
</div>
</form>
I wanted to make a custom validator but for some reason it's not working at all. The required does work so there is no issue with finding the elements in my page. So is there someone who has any idea why it is not working?
Thans in advance, under here you find the code i'm using including the method I wrote and the start of the validate method.
You can't just insert a comparison operator all by itself as the parameter; you need a function that returns the value of this parameter, in this case a boolean from the comparison operator...
$('#form1').validate({
rules: {
txtINSZ: {
required: function() {
return $('#cbInsz').prop('checked') == false;
},
insz: function() {
return $('#cbInsz').prop('checked') == false;
}
....
Solved it, I just putted the rules out of the rules section. After the validation code I putted this:
$('#txtINSZ').rules("add", {
required:true,
insz:true
})
Works perfectly.
I also faced the same situation, but in my case below two steps worked.
use data-rule-insz="true" attribute on your HTML input element for which you want custom validation.
also add a name attribute as mentioned in the below example:-
<input id="customer" name="customer" data-rule-insz="true" required type="text" class="typeahead form-control" />
So I am having a little problem creating a very simple query form due to my lack of understanding about coding. As you can see in the app.js below, I have FormController, which retrieves information from the form, feeds it into the jsonUrlGen function which creates a custom URL, which is then sent to my SolrController which accesses that URL and pulls the JSON information from it.
However it is quite clear after taking a step back and looking at it that the structure of my code is wrong, and I am missing an app.service to link the shared variables between my two controllers. I'm also not even sure if I need two controllers in this instance, but it just happened as I was coding it.
If anybody can tell me what I'm doing wrong here I would really appreciate it, because the code just flat out does not work.
Thanks.
.HTML FILE
<html ng-app="solrApp">
<head>
<link link rel="stylesheet" href="bootstrap-3.3.5-dist/css/bootstrap.min.css" />
<link link rel="stylesheet" href="style.css" />
<script src="https://code.angularjs.org/1.4.3/angular.min.js"></script>
<script type= "text/javascript" src="app.js"></script>
</head>
<body>
<!--<h1 class="headline">Logo or Something Here</h1>-->
<div class="logo"><img src="images/CubedE.png" id="cubedE"/></div>
<div class = "queryForm" ng-controller="FormController">
<input type="text" class="queryBox" id="mainQueryString" placeholder="Query String" ng-model="fullQuery.queryString"><br />
<input type="text" class="queryBox" placeholder="Filter Query" ng-model="fullQuery.filterQuery"><br />
<input type="text" class="queryBox" placeholder="Sort By" ng-model="fullQuery.sortBy"><br />
<h2>Extract only from rows:</h2>
<input type="text" class="halfQueryBox" placeholder="Start" ng-model="fullQuery.startRow"><input type="text" class="halfQueryBox" placeholder="End" ng-model="fullQuery.endRow"><br />
<input type="text" class="queryBox" placeholder="Field List (Separate by comma)" ng-model="fullQuery.fieldList"><br />
<input type="text" class="queryBox" placeholder="Raw Query Parameters (key1=val1&key2=val2)" ng-model="fullQuery.rawQuery"><br />
<button type="button" ng-click="jsonUrlGen()">Submit Query</button>
</div>
<div class = "results" ng-controller="SolrController">
<ul>
<li ng-repeat="item in items">
{{ item.key }} - <em>{{ item.value }}</em>
</li>
</ul>
</div>
</body>
</html>
APP.JS
(function(){
var app = angular.module('solrApp', []);
app.controller('FormController', function($scope) {
$scope.fullQuery = {
queryString: '',
filterQuery: '',
sortBy: '',
startRow: '',
endRow: '',
fieldList: '',
rawQuery: ''
}
$scope.jsonUrlGen = function(){
var jsonURL = "http://localhost:8983/solr/core/select?";
if($scope.fullQuery.queryString !== '') {
jsonURL = jsonURL + "q=" + $scope.fullQuery.queryString;
}
else if($scope.fullQuery.filterQuery !== '') {
jsonURL = jsonURL + "&fq=" + $scope.fullQuery.filterQuery;
}
else if($scope.fullQuery.sortBy !== '') {
jsonURL = jsonURL + "&sort=" + $scope.fullQuery.sortBy;
}
else if($scope.fullQuery.startRow !== '') {
jsonURL = jsonURL + "&start=" + $scope.fullQuery.startRow;
}
else if($scope.fullQuery.endRow !== '') {
jsonURL = jsonURL + "&rows=" + $scope.fullQuery.endRow;
}
else if($scope.fullQuery.fieldList !== '') {
jsonURL = jsonURL + "&fl=" + $scope.fullQuery.fieldList;
}
else {
return "exception thrown";
}
jsonURL = jsonURL + "wt=json";
return jsonURL;
};
});
app.controller('SolrController', function($scope, $http){
$http.get($scope.jsonUrlGen)
.then(function(res){
$scope.items = res.data;
});
});
})();
Answers may be opinionated since there are multiple ways to accomplish this.
I would advise to restructure html. Have a single controller that wraps the "form" and the contents of SolrController. Also the "form" should really become a <form>. In angular there is a default controller created for this tag and it helps a lot with managing validation and handling submit.
<div class="results" ng-controller="SolrController">
<form class="queryForm" name="queryForm" ng-submit="submit()">
<input type="text" class="queryBox" id="mainQueryString" placeholder="Query String" ng-model="fullQuery.queryString"><br />
<input type="text" class="queryBox" placeholder="Filter Query" ng-model="fullQuery.filterQuery"><br />
<input type="text" class="queryBox" placeholder="Sort By" ng-model="fullQuery.sortBy"><br />
<h2>Extract only from rows:</h2>
<input type="text" class="halfQueryBox" placeholder="Start" ng-model="fullQuery.startRow"><input type="text" class="halfQueryBox" placeholder="End" ng-model="fullQuery.endRow"><br />
<input type="text" class="queryBox" placeholder="Field List (Separate by comma)" ng-model="fullQuery.fieldList"><br />
<input type="text" class="queryBox" placeholder="Raw Query Parameters (key1=val1&key2=val2)" ng-model="fullQuery.rawQuery"><br />
<button ng-disabled="queryForm.$invalid">Submit Query</button>
</form>
<ul>
<li ng-repeat="item in items">
{{ item.key }} - <em>{{ item.value }}</em>
</li>
</ul>
</div>
Mind name attribute for the form. It will help to access the form in the scope. Actually when there is a name angular creates $scope.queryForm in parent controller
By default all buttons (and <input type="submit") on form submit on click. But type="button" will prevent it. So remove it
Controller SolrController. It's inappropriate to perform a request before user had a change to input something. $http.get should work on a click handler which we choose to be submit event.
app.controller('SolrController', function($scope, $http){
$scope.fullQuery = {};//ng-model will take care of creating all properties
function jsonUrlGen(){ //same code here
}
$scope.submit = function(){
$http.get(jsonUrlGen())
.then(function(res){
$scope.items = res.data;
});
});
};
})
Hope this helps
So I have a knockout prototype where you add inputs dynamically and then set each of their own settings. Think of its as a form builder is such. However, I noticed that disabled and required doesn't work that great. It sets the value to disabled or required but when I turn it into false it still remains on the element without its state, causing it to still function. Please can anyone help or give guidance.
HTML
<div class="leftpanel">
<div class="input-row" data-bind="foreach: inputItems">
<div class="input-row-item">
<div class="input-item">
<label data-bind="text: label"></label>
<input data-bind="attr:{ name: name, placeholder: placeholder, disabled: disabled, value: value, type: type }">
</div>
<div class="input-settings">
<input type="text" class="nb-remove" data-bind="value: label" placeholder="input label">
<input type="text" value="text" class="nb-remove" data-bind="value: type" placeholder="input type">
<input type="text" class="nb-remove" data-bind="value: name" placeholder="input name">
<input type="text" class="nb-remove" data-bind="value: placeholder" placeholder="input placeholder">
<input type="text" class="nb-remove" data-bind="value: disabled" placeholder="input disabled">
<input type="text" class="nb-remove" data-bind="value: value" placeholder="input value">
</div>
</div>
</div>
</div>
<div class="rightpanel">
Here be draggables!
<br/>
<button data-bind="click: addInput">ADD TEXT INPUT</button>
</div>
The JS
$(function(){
var InputItem = function InputItem(label, type, name, placeholder, disabled, value) {
this.label = ko.observable(label);
this.type = ko.observable(type);
this.name = ko.observable(name);
this.placeholder = ko.observable(placeholder);
this.disabled = ko.observable(disabled);
this.value = ko.observable(value);
}
var ViewModel = function ViewModel() {
var that = this;
this.inputItems = ko.observableArray([]);
this.addInput = function addInput() {
that.inputItems.push(new InputItem());
};
}
ko.applyBindings(new ViewModel());
});
You better use Knockout's own built-in disable binding-handler:
<input data-bind="disable: disabled, attr: { name: name, placeholder: placeholder, value: value, type: type }" />
See Fiddle
Alternatively, you can check for explicit 'truthfulness' in your condition so that Knockout will remove the attribute if the condition is not met. For example:
<input data-bind="attr: { disabled: disabled() === 'true', ...}" />
See this Fiddle (type 'true' in the 'disabled' input to activate disabled).
How can I have 2 inputs instead of just one in Bootstrap's Bootbox?
I need to receive 2 values in a modal dialog.
Actually, there is a simpler way which doesn't require you to modify bootbox code.
The string you pass at the bootbox creation doesn't have to be only text: it can also be html code. That means you can include pretty much everything in the box.
To put a custom form in a bootbox, you can then create it as follow :
bootbox.confirm("<form id='infos' action=''>\
First name:<input type='text' name='first_name' /><br/>\
Last name:<input type='text' name='last_name' />\
</form>", function(result) {
if(result)
$('#infos').submit();
});
I just made function for that, check it out - here
Usage example
bootbox.form({
title: 'User details',
fields: {
name: {
label: 'Name',
value: 'John Connor',
type: 'text'
},
email: {
label: 'E-mail',
type: 'email',
value: 'johnconnor#skynet.com'
},
type: {
label: 'Type',
type: 'select',
options: [
{value: 1, text: 'Human'},
{value: 2, text: 'Robot'}
]
},
alive: {
label: 'Is alive',
type: 'checkbox',
value: true
},
loves: {
label: 'Loves',
type: 'checkbox',
value: ['bike','mom','vg'],
options: [
{value: 'bike', text: 'Motorbike'},
{value: 'mom', text: 'His mom'},
{value: 'vg', text: 'Video games'},
{value: 'kill', text: 'Killing people'}
]
},
passwd: {
label: 'Password',
type: 'password'
},
desc: {
label: 'Description',
type: 'textarea'
}
},
callback: function (values) {
console.log(values)
}
})
For me, this is the cleanest way to do it :
var form = $('<form><input name="usernameInput"/></form>');
bootbox.alert(form,function(){
var username = form.find('input[name=usernameInput]').val();
console.log(username);
});
Create hidden div with form in HTML and inject this html to bootbox message. Snippet below.
var buttonClick = function() {
var bootboxHtml = $('#js-exampleDiv').html().replace('js-exampleForm', 'js-bootboxForm');
bootbox.confirm(bootboxHtml, function(result) {
console.log($('#ex1', '.js-bootboxForm').val());
console.log($('#ex2', '.js-bootboxForm').val());
});
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootbox.js/4.4.0/bootbox.min.js"></script>
<div id="js-exampleDiv" hidden>
<form class="js-exampleForm">
<div class="col-sm-12">
<input placeholder="Example placeholder 1" id="ex1" />
</div>
<div class="col-sm-12">
<input placeholder="Example placeholder 2" id="ex2" />
</div>
</form>
</div>
<button onclick="buttonClick();">
Open bootbox confirm dialog.
</button>
You have to write your own function which will load dialog function from bootbox.
The easiest way is to copy prompt function from source: https://raw.github.com/makeusabrew/bootbox/v3.2.0/bootbox.js
and change this part for adding new input (or whatever you need)
// let's keep a reference to the form object for later
var form = $("<form></form>");
form.append("<input autocomplete=off type=text value='" + defaultVal + "' />");
and this part for getting result:
var confirmCallback = function() {
if (typeof cb === 'function') {
return cb(form.find("input[type=text]").val());
}
};
Here is a basic example for what you need (using knockout)
<button data-bind="click: select">Button</button>
<script type="text/html" id="add-template">
<div style="display:none">
<input data-bind='value: name' placeholder="Name">
</div>
</script>
var viewModel = function () {
var self = this;
self.name = ko.observable();
self.select = function () {
var messageTemplate = $($("#add-template").html());
ko.applyBindings(self, messageTemplate.get(0));
messageTemplate.show();
bootbox.confirm({
title: "Add new",
message: messageTemplate,
callback: function (value) {
// do something
}
});
}
}
ko.applyBindings(new viewModel());
Just add as many fields and bind them in the view model
http://jsfiddle.net/6vb7e224/2/
haradwaith Has the best solution for posting form data from a bootbox. Because it works, it's simple and because he demonstrates how to Actually Submit the Form. His solution:
bootbox.confirm("<form id='infos' action=''>\
First name:<input type='text' name='first_name' /><br/>\
Last name:<input type='text' name='last_name' />\
</form>", function(result) {
if(result)
$('#infos').submit();
});
Moving the <form> tag outside of the bootbox object allows the use of PHP when posting to self and to include hidden inputs without all the clutter.
<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>" id="infos">
<input type=hidden form="infos" name="created" value="<?php echo date("Y-m-d H:i:s"); ?>" />
</form>
Now you can check for $_POST['created']
<?php
if(isset($_POST['created'])){
echo "Timestamp: ".$_POST['created']; // great things happen here
}
?>
You can create the form anywhere in the body tag, it won't display because the inputs are hidden.
Hope that helps!
I know this question is pretty old now, but this is the way I've done it. I think this way is great for larger forms as putting all of the HTML in JavaScript can get ugly pretty quick.
This example uses Bootstrap but the idea is the same. Create a hidden form in HTML and then select it using JavaScript or JQuery.
HTML:
<div id="hiddenForm" class="hidden">
<form id="myForm" class="form-horizontal">
<div class="form-group">
<label class="control-label col-sm-2">First Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="FirstName" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">Last Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="LastName" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">City</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="City" />
</div>
</div>
<div class="form-group">
<label class="control-label col-sm-2">State</label>
<div class="col-sm-10">
<input type="text" class="form-control" name="State" />
</div>
</div>
</form>
</div>
JavaScript Version:
var form = document.getElementById("hiddenForm").innerHTML;
bootbox.confirm({
message: form,
callback: function (result) {
// do something
}
});
JQuery Version:
var form = $("#hiddenForm").html();
bootbox.confirm({
message: form,
callback: function (result) {
// do something
}
});
Note:
When you try to serialize the form for posting, you'll have to make sure you are actually targeting the right form. $("#myForm").serialize() will most likely not work as it will grab the actual HTML form that you built earlier. So instead, you should do something like $(".bootbox-body #myForm").serialize() to get the current form's values.