AngularJS in ASP.NET MVC Partial View - asp.net

I am currently loading Partial View returned by MVC controller to a bootstrap model via AngularJS $http.get call. My View in rendered properly in modal dialog, but the only problem is that my partial view which is rendered also uses angular and for some reason angular is not working in my partial view, but if the i convert the same partial view to a normal view it works properly.
Partial View Code:
#{
ViewBag.Title = "Add Article Types";
}
//other scripts files e.g app.js and angular.js are included in main layout file.
<script src="~/Scripts/Angular/ArticleTypeController.js"></script>
<div class="modal-content" ng-controller="ArticleTypeController">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
Add New Article Type
</div>
<form novalidate role="form" name="ArticleTypeForm" ng-submit="ArticleTypeForm.$valid && Add(model)">
<div class="modal-body">
<div class="form-group">
<label for="ArticleType" class="control-label">Article Type</label>
<input type="text" required ng-model="model.ArticleTypeName" class="form-control" id="ArticleType" />
</div>
</div>
</form>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary" value="Add" >Add</button>
{{ArticleTypeForm.$valid}}
</div>
</div>
Controller to load modal with the partial view.
MenuController.js
angular.module('myApp').controller('MenuController', [
'$scope', '$http', 'httpPreConfig', function ($scope, $http, httpPreConfig) {
$scope.AddArticleType = function () {
$.get("/ArticleType/Add")//returns the partial view.
.success(function (response) {
ShowModal(response);//it properly shows the modal. but angular doesn't work
});
}
}]);
As you can see from the image below that angular expression is not being evaluated.
Any help would be really appreciated.
Just so that you know, angular expressions etc. are working in normal views.

Perhaps the view you're returning is not compiled by Angular. Try compiling it before displaying it in the modal by the $compile service and linking to a correct scope:
$scope.AddArticleType = function () {
$.get("/ArticleType/Add")
.success(function (response) {
$compile(response)($scope);
ShowModal(response);
});
}
But actually, this is not the right thing to do in the Angular world. IMO it would be better to use ng-include to load your content inside the modal and then show it to the user.

Related

Multiple submit button fail to find the handler method in asp.net core 3.1 razor page application

I have a single form which has two button one to upload image using ajax call & other is main submit button which saves all the data.
I am still very new to asp.net core and trying different thing to learn asp.net core with razor page.
I read lot of article about multiple form submit but most of then where using two form with submit button for each.
My issue is when i hit the submit button it fails to find the handler method, after full days troubleshoot nothing worked and last few article point to error/failure to antiforgery, i not sure how to implement it in below code as i tried few but they gave error may be article where old referencing core 2.2 etc example1 example2
I am not sure about the what exactly is causing the issue any help would be appreciate.
I am trying to upload Image using Ajax method in asp.net core Razor pages, I am main form in will all input fields are kept and with the form for Fileupload i am also added addition button which is for file upload using Ajax, When i hit the
<input type="submit" value="Upload Image" asp-page-handler="OnPostUploadImage" id="btnUploadImage" />
i want it to call OnPostUploadImage method in pageModel file but it alway goes to default OnPost method. when i rename the OnPost to OnPost2 nothing happend..
How can i call OnPostUploadImage() on button btnUploadImage click event.
When i hit click btnUploadImage it generates following error on browser console
Error in FF
XML Parsing Error: no root element found Location:
https://localhost:44364/Admin/News/NewsCreate?handler=OnPostUploadImage
Line Number 1, Column 1:
Error in Chrome
jquery.min.js:2 POST
https://localhost:44364/Admin/News/NewsCreateMultipleSubmit?handler=OnPostUpLoadImage
400 (Bad Request)
event though path looks fine but it cant find it as per error message
#page
#model BookListRazor.Pages.Admin.News.NewsCreateModel
#{
ViewData["Title"] = "News Create";
Layout = "~/Pages/Shared/_LayoutAdmin.cshtml";
}
<div class="border container" style="padding:30px;">
<form method="post" enctype="multipart/form-data">
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<input hidden asp-for="News.NewsImage" />
<input id="fileName" hidden value="" />
<div class="form-group row">
<div class="col-2">
<label asp-for="News.NewsHeading"></label>
</div>
<div class="col-10">
<input asp-for="News.NewsHeading" class="form-control" />
</div>
<span asp-validation-for="News.NewsHeading" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-2">
<label asp-for="News.NewsImage"></label>
</div>
<div class="col-10">
#*<input asp-for="News.NewsImage" type="file" class="form-control" id="NewsImage">*#
#*Photo property type is IFormFile, so ASP.NET Core automatically creates a FileUpload control *#
<div class="custom-file">
<input asp-for="NewsImageForUpload" class="custom-file-input form-control">
<label class="custom-file-label">Click here to change photo</label>
<input type="submit" value="Upload Image" asp-page-handler="OnPostUploadImage" id="btnUploadImage" />
</div>
</div>
<span id="imageStatus" class="text-danger"></span>
<span asp-validation-for="NewsImageForUpload" class="text-danger"></span>
</div>
<div class="form-group row">
<div class="col-3 offset-3">
<input id="btnSave" type="submit" value="Create" class="btn btn-primary form-control" />
</div>
<div class="col-3">
<a asp-page="Index" class="btn btn-success form-control">Back to List</a>
</div>
</div>
</form>
<script src="~/lib/jquery/dist/jquery.min.js"></script>
<script src="https://cdn.ckeditor.com/4.14.0/full/ckeditor.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
$(document).ready(function () {
$("#btnSave").addClass("disable-button");
$('.custom-file-input').on("change", function () {
var fileName = $(this).val().split("\\").pop();
$(this).next('.custom-file-label').html(fileName);
$("#fileName").val(fileName);
$("#btnSave").removeClass("disable-button");
});
if ($("#fileName").val() == "") {
//alert("Select Image...");;
}
});
</script>
</div>
#section Scripts{
<partial name="_ValidationScriptsPartial" />
<script>
$(function () {
$('#btnUploadImage').on('click', function (evt) {
console.log("btnUploadImage");
evt.preventDefault();
console.log("btnUploadImage after evt.preventDefault()");
$.ajax({
url: '#Url.Page("", "OnPostUploadImage")',
//data: new FormData(document.forms[0]),
contentType: false,
processData: false,
type: 'post',
success: function () {
alert('Uploaded by jQuery');
}
});
});
});
</script>
}
.cs file CODE
public async Task<IActionResult> OnPost()
{
if (ModelState.IsValid)
{
return Page();
}
else
{
return Page();
}
}
public IActionResult OnPostUploadImage()
{
//Some code here
}
Verify that you add the following code to the ConfigureServices method of startup.cs:
services.AddAntiforgery(o => o.HeaderName = "XSRF-TOKEN");
If you want to enter the OnPostUploadImage method, the url of the Ajax request needs to be changed to #Url.Page("", "UploadImage") without adding OnPost.
And the Ajax request should send the anti-forgery token in request header to the server.
Change your ajax as follow:
#section Scripts{
<partial name="_ValidationScriptsPartial" />
<script>
$(function () {
$('#btnUploadImage').on('click', function (evt) {
console.log("btnUploadImage");
evt.preventDefault();
console.log("btnUploadImage after evt.preventDefault()");
$.ajax({
url: '#Url.Page("", "UploadImage")',
//data: new FormData(document.forms[0]),
contentType: false,
processData: false,
beforeSend: function (xhr) {
xhr.setRequestHeader("XSRF-TOKEN",
$('input:hidden[name="__RequestVerificationToken"]').val());
},
type: 'post',
success: function () {
alert('Uploaded by jQuery');
}
});
});
});
</script>
}
You can refer to this for more details.

Form action called before ajax request

I'm trying to validate some data using javascript, so after created this form:
<form asp-controller="User" asp-action="UpdateUser" asp-antiforgery="true" id="userInformations">
<div class="form-group">
<label class="col-lg-6 control-label">#Localizer["OldPassword"] (*)</label>
<div class="col-lg-12">
<input class="form-control" required id="oldPassword"
asp-for="#Model.ExistingPassword" type="password" />
</div>
<div class="form-group">
<label class="col-lg-6 control-label">#Localizer["NewPassword"] (*)</label>
<div class="col-lg-12">
<input class="form-control" required id="newPassword"
asp-for="#Model.Password" type="password" />
</div>
</div>
<button type="submit" class="btn btn-primary">Store</button>
</form>
I binded a javascript function that intercept the submit:
$('#userInformations').on('submit', function (event) {
event.preventDefault();
//validate some fields
//execute ajax request
$.ajax({
url: $(this).attr('action'),
type: "POST",
data: $(this).serialize(),
success: function (result) {
alert(true);
console.log(result)
},
error: function (data) {
console.log(data);
}
});
});
Now when I press the submit button, the method UpdateUser in the UserController is called first of the javascript function, and I don't understand why happen this because I used preventDefault.
How can I prevent to call the asp net action binded to the form?
The effect you want is to use javascript to validate some data , and implement the action call through ajax when you press the submit button?
I use the code you provided and it works.
Try the following two ways:
1.Add the following piece of code above your javascript
<script src="~/lib/jquery/dist/jquery.js"></script>
2.Or directly write your javascript in #section Scripts { }
If you want JavaScript first than you have to remove asp-Controller and action from form, than you can validate form by JavaScript and send data through Ajax call to Controller/action.

Meteor Bootstrap 3 Form does not Submit

I'm working with meteor#1.1.10 and twbs:bootstrap#3.3.5
I can get a modal window to spawn, close, and register a button has been clicked. I cannot get it to read any information from a form though. It just closes. I included a console message and it never shows up to either the browser or the command prompt.
Is there a way to do this without including another package? I've included my modal HTML template and Javascript. I'm hoping it's just something missed in the code.
Below is the HTML:
<template name="emodal">
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Spends Email Details</h4>
</div>
<div class="modal-body">
<form class="emailspends">
<label for="input">Recipient:</label>
<input type="text" name="emailto" required>
<label for="input">Character Name:</label>
<input type="text" name="charname" required>
<input type="submit" id="sendemail" class="email" value="Email Spends" data-dismiss="modal">
</form>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
</template>
Below is the Javascript:
Template.emodal.events({
"submit .emailspends": function (event) {
console.log(Meteor.user().emails[0].address);
// Prevent default browser form submit
event.preventDefault();
// Get value from form element
//var emailto = event.target.emailto.value;
var emailto = event.target.emailto.value;
var charname = event.target.charname.value;
var title = "Experience spends for " + charname;
Meteor.call('sendEmail', emailto,
'zbottorff#uwalumni.com', title,
'Yup, modal testies.');
// Clear form
event.target.emailto.value = "";
event.target.charname.value = "";
}
});
Update: Realized I should include this, but I did make sure I could get a submit-able template without it being in a modal window. Now I want to turn it into a modal and it's not submitting.
Bah! I found it just after I posted this.
I had too many parts to my submit button. I removed the "Class" and "id" parts, changed my Javascript to look for a 'submit form' event instead. Voala! Got the bugger to work.

Ui-bootstrap-modal with ui-bootstrap-tpls-0.13 and bootstrap 3.3.2, angular 1.3.14 not working

As mentioned in the title, the modal does not show up.
The content of the form is loaded via formly and the content of the template seems to load, but it only shows the modal very thin, with the overlay but not the content.
I have a main controller in which I have:
$scope.add = function(){
$modal.open({
templateUrl: 'app/js/templates/popupAddCarForm.html',
controller: 'FormsController',
controllerAs: 'vm',
backdrop: 'static',
resolve: {
formData: function(){
return {
fields: getFormFields(),
model: {}
}
}
}
});
};
My html is like so:
<script type="text/ng-template" id="popupAddCarForm">
<div class="modal">
<div class="modal-dialog">
<div class="modal-header">
<h3 class="modal-title">Adauga masina</h3>
</div>
<div class="modal-body">
<form name="vm.addCarForm">
<formly-form model="vm.formData.model" fields="vm.formData.fields">
</formly-form>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="submit" >Adauga</button>
</div>
</div>
</div>
And my form controller like so:
davidintercar.controller('FormsController',
function($modalInstance, formData) {
var vm = this;
//debugger;
vm.formData = formData;
vm.originalFields = angular.copy(vm.formData.fields);
}
);
The result is like so:
LATER EDIT:
In order to rid ourselfes of other doubts, here is the code from the demo:
app.controller('ModalInstanceCtrl', function ($modalInstance, formData) {
var vm = this;
debugger;
// function assignment
vm.ok = ok;
vm.cancel = cancel;
// variable assignment
vm.formData = formData;
vm.originalFields = angular.copy(vm.formData.fields);
// function definition
function ok() {
$modalInstance.close(vm.formData.model);
}
function cancel() {
$modalInstance.dismiss('cancel');
};
});
Link: angular-formly.com/#/example/integrations/ui-bootstrap-modal
LATER, LATER EDIT:
Plunker: http://plnkr.co/edit/8wgL4t2oXsFFeLBKGGW8?p=preview
Folder Structure:
--app
----js
------controller
------services
------templates
------view
----app.js
intex.html
My popupAddCarForm.html is in the templates directory, but as you see in the plunker, it does not render my loaded content, even in the same directory although a separate template file.
The modal template don't need to have the modal and modal-dialog layer - they will be generated by bootstrap.
<script type="text/ng-template" id="popupAddCarForm.html">
<div class="modal-header">test
<h3 class="modal-title">Adauga masina</h3>
</div>
<div class="modal-body">
<form name="vm.addCarForm">
<formly-form model="vm.formData.model" fields="vm.formData.fields">
</formly-form>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-default" type="submit" >Adauga</button>
</div>
</script>

Iron:Router url parameter to modify nested layout

I'm really struggling with this one. If you want to view what I have bludgeoned together, it is all in a repo on GitHub called instructor-oracle. What I would like to do is have the landing page be the layout at ./wbs. Then I would like the search to route to ./wbs/:_wbsCode and populate the sidebar with the appropriate record. I am thinking the router needs to be structured something like...
Router.configure({
layoutTemplate: 'layout'
});
Router.map(function () {
this.route('wbs', {
path: '/wbs'
}, function () {
this.render('wbs-detail', {
path: '/wbs/:_wbsAbbrev',
to: 'wbs-detail',
data: function () {
theOne = Wbs.findOne({abbrev: this.params._wbsAbbrev});
console.log(theOne.abbrev);
return theOne;
}
});
});
...and this would be paried with templates like...
<template name="layout">
<header class="container-fluid">
<nav class="navbar navbar-default" role="navigation">
<div class="navbar-header">
<a class="navbar-brand" href="{{pathFor 'wbs'}}">Instructor Oracle</a>
</div>
<div class="collapse navbar-collapse" id="bs-navbar-collapse">
<form class="navbar-form navbar-left" role="search" id="wbsSearchForm">
<div class="form-group">
<input
class="form-control typeahead"
name="wbsSearch"
id="wbsSearch"
type="text"
placeholder="Search"
autocomplete="on"
spellcheck="off"
autofocus="true"
/>
</div>
<button type="submit" class="btn btn-default">Find</button>
</form>
</div>
</nav>
</header>
<main class="container-fluid">
{{> yield}}
</main>
</template>
<template name="wbs">
<div class="col-sm-3" id="wbsCol">
{{> yield 'wbs-detail'}}
</div>
<div class="col-sm-9" id="timesheetCol">
<iframe src="http://iframeurl.html" id="timesheetFrame"></iframe>
</div>
{{#contentFor 'wbs-detail'}}
<h1>{{abbrev}} <small>{{code}}</small></h1>
{{/contentFor}}
</template>
...and an event handler for the form like this...
Template.layout.events({
// catch submit event for wbs form
'submit': function (event, template) {
// prevent default behavior and stop bubbling
event.preventDefault();
event.stopPropagation();
// store dom element in variable
var inputElement = template.find('input#wbsSearch');
// access value in form and extract abbreviation if found
var abbrev = Wbs.findOne({abbrev: (inputElement.value).toUpperCase()}).abbrev;
// clear input
inputElement.value = "";
// go to the page
Router.go('wbs-edit', {_wbsAbbrev: abbrev});
}
});
I have been trying to sort through this on the iron:router documentation, but right now I am all kinds of lost (obviously). Still, I need this to work to avoid reloads on the main layout template so the iframe does not reload while the sidebar can change along with the matching url so links to specific sidebar content can be bookmarked and shared.
Thank you in advance for your assistance. If I eventually sort all of this out, I am more than happy to contribute to the iron:router documentation so it makes sense for the next pea-brained idiot like myself who happens to need to sort this out.

Resources