knockout.js afterRender does not work in a jquery pop-up - javascript

<div data-bind="style: { display: !koIsHidden() ? 'inline-block' : 'none'}">
<button id="hideButton" type="button" title="Hide" onclick="javascript:openJuiPopup('#hidePopup')" style="background: none; border: none">
<i id="hideCross" class="fa fa-2x fa-times" data-bind="attr: { 'data-applicationKey': application.applicationKey }"></i>
</button>
</div>
This button loads a pop-up that looks like this
The code for the popup looks like:
<div id="hidePopup" class="popup ui-content" data-role="popup">
<!-- ko foreach: { data: previewApplications(), afterRender: renderPopup} -->
<form id="hider" style="display:inline;" method="post" data-bind="attr: {action: '#(MVC.GetLocalUrl(MVC.HireOrgJobApplication.ViewApplication(Model.CurrentOrganization.CustomUrl, Model.Job.JobKey, "xxx/ajax-hide")))'.replace('xxx', application.applicationKey)}">
#Html.AntiForgeryToken()
<input type="hidden" name="ApplicationKey" data-bind="attr:{ value : application.applicationKey }" />
<input type="hidden" name="HideReasonId" value="7" />
<button type="submit" class="btn btn-danger jui-tooltip" data-bind="text: application.hideButtonSendRejectionInsteadOfHide === true ? 'Reject' : 'Hide', attr: { title: application.hideButtonSendRejectionInsteadOfHide === false ? 'Reject' : 'Hide'}"></button>
</form>
<!--/ko-->
</div>
And the js code that calls it:
$("#hidePopup").dialog({
dialogClass: "no-close",
position: { my: "bottom", at: "bottom", of: $("#hideCross"), collision: "none" },
autoOpen: false,
draggable: true,
}).dialog("widget").find(".ui-dialog-titlebar").hide();
The detail isn't that important, but one thing important in this code is
<!-- ko foreach: { data: previewApplications(), afterRender: renderPopup} -->
Due to the afterRender feature of knockout js, this should loop through elements in previewApplications() and run the function renderPopup.
The renderPopup looks like
self.renderPopup = function (element, data) {
$(element).find("form#hider").ajaxForm(function () {
alert("heyyyyy");
});
};
This should just simply find a form with id = hider, and run alert("heyyyy").
But it doesn't work.
Notice that afterRender worked totally fine when i put it outside of the popup.
Please help!
EDIT:
I can add more info to this question.
It's not about afterRender, but the ajaxForm just does not work for the popup.
Any idea?
EDIT2:
self.renderApplication = function (element, data) {
filter: ($(element).filter("form#hider")[0]).ajaxForm(function () {
data.koIsHidden(true);
});
};
I tried this and
$(element).filter(("form#hider")[0]).ajaxForm(function () {
data.koIsHidden(true);
});
The code above gives me the error that i wrote in the comment, and the second one gives me no error, but still doesnt catch the renderApplication function.

Call renderPopup like a function - afterRender: renderPopup() or you may have to try $root.renderPopup() or $parent.renderPopup().

Related

Uncaught Reference Error: function StartOver() is not defined at HTMLButtonElement.onclick

I have using an Iframe from third party in my razor view page for payment processing, and I want to implement Start Over and Finish Up button using javascript at the bottom section of the page. The script tag to submit init form need to be as it is otherwise the Iframe will not load . All the necessary libraries are included in layout page.
View page Code -
#{
ViewData["Title"] = "Payment Page";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#model MyModel
<p></p>
<div class="row ">
<div class="col-md-12">
<div class="panel panel-primary panel-title">
<div class="panel-heading text-bold">Embedded UI Component</div>
<div class="panel-body">
<iframe name="client" style="width:100%;height:600px;position:center;left:0;top:0;border:thick"></iframe>
<form action="#Model.IframeUrl" id="initForm" target="client" method="POST" style="display:none">
<input name="X-BEARER-TOKEN" value="#Model.AgentAccessToken">
<input name="X-REFRESH-TOKEN" value="#Model.AgentRefreshToken">
</form>
</div>
</div>
</div>
</div>
<div class="row ">
<div class="col-md-12">
<div class="panel panel-primary panel-title">
<div class="panel-heading text-bold">Payment Section Bottom</div>
<div class="panel-body" style="width:100%;height:150px;position:center;left:0;top:0;border:thick">
<h6 style="font-style:italic;color:red">[Populate here.]</h6>
#Html.Hidden("sessionGuid", "#Model.SessionGuid.ToString()")
<form>
<button id="start" class="btn btn-info" onclick="StartOver()">Start Over</button>
<button id="finish" class="btn btn-primary" onclick="FinishUp()">Finish Up</button>
</form>
</div>
</div>
</div>
</div>
<script>
document.getElementById("initForm").submit();
</script>
<script>
debugger;
function StartOver() {
//e.preventDefault();
/* if (confirm("Are you sure you want to start over the Payment Process?")) {
console.log("pressed yes");
}
else {
console.log("pressed no");
}*/
bootbox.confirm({
message: "Are you sure you want to start over the Payment Process?",
buttons: {
confirm: {
label: 'Yes',
className: 'btn-success'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
var email = #Model.Email;
debugger;
if (result)
{
if (result) {
var request = $.ajax({
url: 'MyController/StartOverSession',
type: 'GET',
data: { Email = email },
contentType: 'application/json; charset=utf-8'
});
}
}
}
});
}
function FinishUp() {
bootbox.confirm({
message: "Are you sure you want to finish the Payment Process?",
buttons: {
confirm: {
label: 'Yes',
className: 'btn-success'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
if (result) {
window.location.href = "/Thankyou.cshtml";
}
}
});
}
</script>
When I click on Start Over button, I get "StartOver() is not defined at HTMLButtonElement.onclick ". The scripts tags are within tags of HTML. I have checked other related question for this error, but they are not helpful as most of them are either syntax error or jsfiddle settings related. The confirm() method in the comments works.
The default type value for a <button> element is "submit", so your "Start Over" button is triggering a form submission.
The JavaScript confirm() function will generate a dialog which will block the page (and therefore the form submission) processing until it has been dismissed. Bootbox's functions can't do that - all it's really doing is generating a Bootstrap modal on the fly. Bootstrap modals are just positioned <div> elements, so there's no page blocking (nor can there be). We do cover this in the Known Limitations section of the documentation.
Two options, based on your code:
Set the type attribute on both buttons to "button".
<form>
<button type="button" id="start" class="btn btn-info" onclick="StartOver()">Start Over</button>
<button type="button" id="finish" class="btn btn-primary" onclick="FinishUp()">Finish Up</button>
</form>
Use the preventDefault() function you've currently commented out in your code. You just need to add e as an parameter for that to work.
debugger;
function StartOver(e) {
// prevent the button's default action (submit, in this case)
e.preventDefault();
bootbox.confirm({
message: "Are you sure you want to start over the Payment Process?",
buttons: {
confirm: {
label: 'Yes',
className: 'btn-success'
},
cancel: {
label: 'No',
className: 'btn-danger'
}
},
callback: function (result) {
var email = '#Model.Email';
debugger;
if (result) {
var request = $.ajax({
url: 'MyController/StartOverSession',
type: 'GET',
data: { Email = email },
contentType: 'application/json; charset=utf-8'
})
.done(function(response, status, jqxhr){
// do something when a successful (status code 200) response is received
})
.fail(function(jqxhr, status, error){
// do something when an error (status code other than 200, including 30x redirects) response is received
});
}
}
});
}

Knockout why does my first form.submit work but not the others?

I have three views which posts a JSON-object to backend to generate a PDF. The first in the hierarchy works, not the two others. The code is practically identical, and uses the same method to programmatically add a hidden input-field with the JSON-data.
I cannot for the life of me figure out what the problem is.
First i thought Knockout was creating the problem since the form-elements are added in a foreach-loop, in a AJAX-success-event, but every view is identical in this respect.
I've tried all variations of renaming, also I've tried to create the form and input programatically, appending them to the body and submitting. Still only the first works.
WORKING VIEW:
<div data-bind="visible: rep.messages().length > 0">
<div data-bind="foreach: rep.messages">
<div id="error" data-bind="css: color">
<div><span data-bind="css: icon"></span></div>
<div><div data-bind="html: text"></div></div>
<div>
<form action="/createPDF.html" method="POST" id="individlonpdf" name="loneandringar" target="_blank">
<span onclick=""></span>
Skriv ut
</form>
</div>
</div>
</div>
</div>
NOT WORKING VIEW:
<div data-bind="visible: rem.newEmployeeMessages().length > 0" id="rem-msg-area">
<div data-bind="foreach: rem.newEmployeeMessages">
<div id="error" data-bind="css: color">
<div><span data-bind="css: icon"></span></div>
<div><div data-bind="html: text"></div></div>
<div>
<form action="/createPDF.html" method="POST" id="ateranstallpdf" name="avanmalan" target="_blank">
<span onclick=""></span>
Skriv ut
</form>
</div>
</div>
</div>
</div>
JAVASCRIPT
Each click event-method is then directed towards the same print-method
Not-working:
rem.print = function(){
mainPdfPrint("ateranstallpdf", data, "avanmalan");
}
Working:
rep.print = function () {
mainPdfPrint("individlonpdf", data, "loneandringar");
}
The main-method:
function mainPdfPrint(formid, datasource, name, stringified) {
formid = "#" + formid;
var url = $(formid).attr("action");
var data = stringified ? datasource : JSON.stringify(datasource);
var inp = $("<input>", { "value": data, "name": name, "type": "hidden" });
if ($(formid + " input:hidden").length) {
$(formid + " input:hidden").remove();
}
$(formid).append(inp);
IK.global.logAnalytics(url);
document.forms[name].submit();
}
Both working and non-working form-elements are part of the document.forms-collection as they should be.
Any suggestions would be greatly appreciated!
UPDATE
After suggestions here, I've tried a different approach:
<div class="col-xs-12" id="" data-bind="visible:messages().length > 0">
<div data-bind="foreach: messages">
<div class="col-xs-12" id="error" data-bind="css:color">
<div class="col-xs-12 msg-templates">
<div class="col-xs-1 no-pad-l info-sign">
<span class="glyphicon" data-bind="css:icon"></span>
</div>
<div class="col-xs-9 no-pad-l">
<div class="col-xs-12 no-pad-lr msg" data-bind="html:text"></div>
</div>
<div class="col-xs-2 no-pad-lr text-right print">
<form class="col-xs-12 no-pad-l" action="/foretag/individkort/skapaPdfAvanmalan.html" method="POST" id="avanmalanpdf" name="avanmalan" target="_blank">
<span class="glyphicon glyphicon-print" onclick=""></span>
<input type="hidden" name="avanmalan" data-bind="value:ko.toJSON($root.printableEmployee)" />
Skriv ut
</form>
</div>
</div>
</div>
</div>
</div>
The problem still persists however, but setting a delay in the print-method triggers the submit-event:
self.print = function () {
setTimeout(function () {
document.forms.avanmalan.submit();
}, 600);
}
Your approach indicates that you seem to be not really familiar with knockout and try to do too much in a "jQuery" kind of way.
With knockout, your user interface is a function of your view model. All changes in the DOM have to be a result of changes in the underlying data. The task of manually adding input fields with JS code is not part of this approach.
In the following, there is no custom code that modifies the DOM. Everything is done by knockout.
var vm = {
rep: {
messages: [
{ color: '', icon: '', text: '<b>Message 1</b> - Text', data: 'some data here 1' },
{ color: '', icon: '', text: '<b>Message 2</b> - Text', data: 'some data here 2' },
{ color: '', icon: '', text: '<b>Message 3</b> - Text', data: 'some data here 3' }
]
},
catchPost: function () {
// dummy function to prevent an actual form POST
console.log("...would send the following data to the server:");
console.log(ko.toJSON(this.data, null, 2));
return false;
}
};
ko.applyBindings(vm);
button.submit {
border: 0px none;
padding: 0;
margin: 0;
text-decoration: underline;
background-color: transparent;
color: blue;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<div data-bind="with: rep">
<div data-bind="foreach: messages">
<div id="error" data-bind="css: color">
<div><span data-bind="css: icon"></span></div>
<div><div data-bind="html: text"></div></div>
<div>
<form action="/createPDF.html" method="POST" target="_blank" data-bind="submit: $root.catchPost">
<input type="hidden" name="loneandringar" data-bind="value: ko.toJSON(data)">
<button class="submit" id="print-tgl">Skriv ut</button>
</form>
</div>
</div>
</div>
</div>
There is no need for any custom code in such a simple scenario. Unless you have an explicit dependency on jQuery UI (or a similar library), I suggest you remove jQuery from your application altogether. You can use a dedicated Ajax library if you require it - such as reqwest - but generally speaking, jQuery is more of a hindrance than a help in knockout applications.

Jquery how send hidden value to my script

I use ASP.NET MVC and Jquery. I have icon, when I click on it shows dialog box.
Reports.cshtml:
<a class="dialog-opener" href="#">
<input type="hidden" name="reportID" value="#view.ReportCode"/>
<i class="material-icons right">more_vert</i>
</a>
in this dialog box I have form it is partial view
SubscriptionForm.cshtml:
<div id="dialog-modal" title="Basic model dialog">
#using (Html.BeginForm("SubscriptionForm", "Subscription", FormMethod.Get)) {
#Html.AntiForgeryToken()
...
</div>
_LayoutForAll.chhtml:
$(function () {
$('#dialog-modal').dialog({
dialogClass: 'ui-dialog-osx',
autoOpen: false,
width: 800,
title:"Formularz subskrypcji",
show: {
duration: 1000
},
hide: {
duration: 1000
}
});
$('.dialog-opener').click(function () {
var reportId = $("[type=hidden]").val();
$("#dialog-modal").dialog("open");
alert(reportId);
});
});
I need send reportId from Reports.cshtml and date from form SubscriptionForm to my controller, I don't now how do this.
give ID to your hidden filed and get value using jquery
<a class="dialog-opener" href="#">
<input type="hidden" id="myhiddenfield" name="reportID" value="#view.ReportCode"/>
<i class="material-icons right">more_vert</i>
</a>
below code use for get value from hidden field.
$('.dialog-opener')
.click(function () {
var reportId = $("#myhiddenfield").val();
$("#dialog-modal").dialog("open");
alert(reportId);
});
try above code . its working fine.

The k-add-button works only one times.

The a href with k-add-button in the viewtemplate works only on times, not multible times. Have anybody a idea why, or mybe a sample or solution that's work correctly?
If the k-add-button is outside from the template, it works fine.
<div id="example"></div>
<script type="text/x-kendo-template" id="viewtemplate">
<div class='k-widget'>
<span>Filter:</span><span>#:filtertext#</span><span>Filterwert:</span><span>#:filterwert#</span>
<a class="k-button k-edit-button" ><span class="k-icon k-edit"></span></a>
<a class="k-button k-delete-button" ><span class="k-icon k-delete"></span></a>
<a class="k-button k-add-button" ><span class="k-icon k-add"></span></a>
</div>
</script>
<script type="text/x-kendo-template" id="editTemplate">
<div class='k-widget'>
<input type="text" class="k-textbox" data-bind="value:filtertext" name="filtertext" required="required" validationMessage="required" />
<span data-for="filtertext" class="k-invalid-msg"></span>
<input type="text" class="k-textbox" data-bind="value:filterwert" name="filterwert" required="required" validationMessage="required" />
<span data-for="filterwert" class="k-invalid-msg"></span>
<a class="k-button k-update-button" ><span class="k-icon k-update"></span></a>
<a class="k-button k-cancel-button" ><span class="k-icon k-cancel"></span></a>
</div>
</script>
<script type="text/javascript">
$(document).ready(function () {
var dataSource = new kendo.data.DataSource({
data: [ { filternr: 0, filtertext: "SA-Code", filterwert:"123"} ],
schema: {
model: {
id: "filternr",
fields: {
filternr: { type: "number" },
filtertext: { type: "string" },
filterwert: { type: "string" }
}
}
}
});
var listView = $("#example").kendoListView({
dataSource: dataSource,
template: kendo.template($("#viewtemplate").html()),
editTemplate: kendo.template($("#editTemplate").html()),
}).data("kendoListView");
$(".k-add-button").click(function(e) {
listView.add();
e.preventDefault();
});
}); // Ende $(document).ready()
</script>
I have modified your code slightly at this dojo: list view template with button
You will hopefully notice the following changes I have made.
I have added a DataBound event to your listview object like so:
editTemplate: kendo.template($("#editTemplate").html()),
dataBound: onDataBound
I have then wrapped your button click event in the appropriate function called onDataBound
The reason the button is not working correctly is that once the data you have added to the dataSource is saved and then re-read the template is re-rendered and this then removes the event handlers from the buttons that you associated then with. In order to re-link them we reattach it as part of the dataBound event and then everything is working happily.
If you need more info let me know.
Hopefully the example shows what it is doing.

How write a script that works on modal popup & on full page

I have the following view which is forced to be displayed as a modal popup using jQuery :-
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" /> | #Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
}
<span id="progress" class="text-center" style="display: none;">
<img src="~/img/ajax-loaders/ajax-loader-5.gif" alt="wait" />
Wait..
</span>
and i wrote the following script, which will fires if the user click on Create/Edit/Delete links . where the script will show a progree message + disable the submit button:-
$(function () {
$.ajaxSetup({ cache: false });
$("a[data-modal]").on("click", function (e) {
$('#myModalContent').load(this.href, function () {
$('#myModal').modal({
height: 1000,
width: 1200,
resizable: true,
keyboard: true
}, 'show');
$('#myModalContent').removeData("validator");
$('#myModalContent').removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse('#myModalContent');
bindForm(this);
});
return false;
});
});
function bindForm(dialog) {
$('form', dialog).submit(function () {
$('.btn btn-default').prop("disabled", "disabled");
$('#progress').show();
if ($(this).valid()) {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
but let say the that the user instead of clicking on the link, he chose to "Open link in new browser" , so the view will render insdie the browser (not as modal popup) and the script will not fire, so when the user click on submit button,, the submit button will not be disabled + the progress will not be shown?
So can anyone adivce where i need to place a script that always works ?

Categories