Directive for loading forms into a single page app lost controller binding - binding

I'm creating a single page app using AngularJS. I have created a main page with a custom directive for loading a form URL. I want to change the the forms based on a variable in my controller. However, I lost my bindings once I compiled and linked the form from URL
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<div ng-app="tradesman" ng-controller="application" class="form-horizontal" role="form">
Hello {{applicant.name}}
<my-form name="formName">
</my-form>
</div>
var tradesman = angular.module("tradesman")
tradesman.controller("application",function application($scope){
$scope.formName="personals";
$scope.applicant={};
});
tradesman.directive("myForm",function($http,$compile){
return {
restrict:"E",
scope:false,
replace:true,
link:function(scope,element,attrs){
var url="http://tradesman.local/views/"+scope.formName+".html";
$http.get(url).then(function(response){
scope.$watch(function(){
element.html(response.data);
$compile(element.contents())(scope);
});
});
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
This has successfully loaded my personals page but lost the binding in that page. More over I want a new form to be loaded whenever I change my formName in controller.
What needs to be done to make form loading and binding work simultaneously

Related

Using VueJS in a ASP project

Currently developing a ASP MVC site.
Some sections of the site will use VueJS for displaying some list, forms etc.
The project setup is Bower, Grunt, standard C# ASP project using TypeScript.
This is my first time using Vue, and the simple stuff is pretty stragt forward. Seting up a page with a form, getting data from a WebService etc.
My problem/question is, what, and how, do i get the best setup, for using Single File Components (Vue) in my cshtml view files.
So, lets say I have a section on my site, where i want to display orders from the user.
Layout, navigation etc is setup by my excisting ASP code. I have a CSHTML viewpage for the current page, pretty vanilla:
#inherits MyViewPage<MyViewModel>
#{
Layout = "~/Views/layout.cshtml";
}
<div id"app">
</div>
Thats it for the excisting view page. In this page, i want to include a Vue Single File Component.
Previously i had the markup directly in the CSHTML page, which works fine. But when i want to user Vue-router, it becomes a problem to maintain the different views. So i should move the markup into a Component.
This is the basic setup;
const page1 = { template: '<div>Page1</div>' }
const page2 = { template: '<div>Page2</div>' }
const routes = [
{ path: '/', component: page1 },
{ path: '/page2', component: page2 }
]
const router = new VueRouter({
routes
})
var vm = new Vue({
router,
el: "#app"
})
Lets say i create a .vue file called page1.vue instead. This contains
<template>
my new page
</template>
<script>
export default {
name: '?',
date: function() {
}
}
</script>
How do i get this file included in my CSHTML file for instance?
You need to develop with webpack to build Single File Components.
See the Vue documentation on this.
Use the Vue Cli and drop a web pack build into your cshtml page.

Get ID from modal window

I have a block of code running 3 times that will display some books and have a button to add a review.
Review button fires a modal popup with form to fill to create a review.
I am feeling dumb but I cant find a way to get a ID of a bookto use to create a review.
Was thinkink to display it within add reiew button params but dont know how to pass it after form submit (with other button pressed withtin form itself)
Template view for each book
<div class="book-#{book.id}">
... other stuff
<button class="review-create"> Write Review </button>
</div>
Javascript to display modal
$('.review-create').click(function(e) {
e.preventDefault();
// might not be parent() here but you can call parent() as many times as you want
var bookId = $(e.currentTarget).parent().attr('class').split('-')[1];
// other stuff for ajax or pass bookId into modal method
// Modal.displayForBook(bookId);
});
Now that your modal has the bookId, you can submit it through ajax by just referencing the variable. Hope this helps.
EDIT:
Because you can't edit the current script, you can write a new script in the view.
_book.html.erb
<script type='javascript/text'>
$('modal-button').click(function(e) {
$('review-create').attr('id', "#{book.id}");
});
</script
modal.html.erb
Your modal will submit ajax, dont make it do the form_for helpers
<script type='javascript/text'>
$('form.create').on('submit', function(e) {
var bookId = $(e.currentTarget).parent().attr('id');
// ajax call here
// on success, $(e.currentTarget).parent().attr('id', null)
});
</script>

Angular Routing in ASP.NET MVC combined

I m having one index page and one child page. In my index page, I m trying to render my child. but somehow things not working as expected and Angular routing not working as expected
Here is my index page
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<body ng-app="AngularApp">
<div> My message {{message1}} </div>
First child
<div></div>
<div ng-view></div>
</body>
#section scripts{
<script src="~/Scripts/angular.js"></script>
<script src="~/Scripts/angular-route.js"></script>
<script src="~/Scripts/angular-resource.js"></script>
<script src="~/Modules/AngularApp.js"></script>
}
Here is my angularApp.Js file where I have defined the routing
var myapp = angular.module('AngularApp', ['ngRoute']);
myapp.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/',
{
templateUrl: '/Index',
controller: 'IndexController'
})
.when('/FirstChild',
{
templateUrl: '/Angular/FirstChild',
controller: 'ChildController'
});
$locationProvider.html5Mode(true).hashPrefix('!')
});
myapp.controller('IndexController', function ($scope) {
alert('My Index');
$scope.message1 = "My Index";
});
myapp.controller('ChildController', function ($scope) {
alert('My Child Index');
$scope.FirstMessage = 'My First Message';
});
Here is my ASP.NET MVC Action for rendering the partial view. My controller name in ASP.NET MVC is Angular
public ActionResult FirstChild()
{
return PartialView("Firstchild");
}
Problem 1:
When I run the application with Index as the start page, this is the URL, I m seeing in the browser, http://localhost:59367/Angular/Index but the corresponding controller in Angular side for index page is not triggered
Problem 2:
When I click the First child link in my index page, its taking me to a completely page rather than rendering the partial view inside the ng-view.
http://localhost:59367/Angular/FirstChild
I m pretty sure there is serious problem in Angular routing which I defined but couldn't figure it out:( Please help
Problem Summary:
On further analysis, its been found that, once I click the "First child", ideally the URL should read like Angular/Index#/FirstChild but what happens here is, "ASP.NET MVC Action First Child is getting called and the URL is changing completely"
Problem has been identified. The article which I followed has used the below part
$locationProvider.html5Mode(true).hashPrefix('!')
in the app.js file. I have removed it due to some issues in my local. But while doing so, I didn't update the part in my index page for this line
First child
It has to be
First child
Now angular routing started working fine without any issues. :)
Updated Question:
I tried including the line in d code and I removed as # in my the href but it was not working.. Seems like angular routing has to be updated as well.
$locationProvider.html5Mode(true).hashPrefix('!')
Can someone help me in updating it in the correct format.

Partial view in a dialog

I have managed to get the JQuery Modal dialog to show and within it, I load a partial view:
var url = '#Url.Action("ShowCarDetail", "Car")?id=' + id;
$('#dialog-modal').dialog(
{
title: "Car Detail",
width: 600,
height: 500,
draggable: false,
close: function (event, ui) {
$(this).dialog('close');
}
});
$('#dialog-modal').load(url, function()
{
$(this).dialog('open');
});
So that works fine. The problem is that when the dialog is closed, and I re-open it, the data is not refreshed. I have a DateTime on that partial view that tells me this so leaving it for a few seconds still shows me the old values.
how can I force the modal dialog to load correctly (without it using the old html that may have been rendered from the previous request)?
also - if the partial view has some actions like a submit or something, will the dialog still remain open or will this refresh the page fully? I want to be able to have that modal dialog similar to an iframe style where any actions that happen within the page in the modal will still be there and be updated without the page having a full refresh and the dialog closing.
thanks
Regarding your question:
also - if the partial view has some actions like a submit or
something, will the dialog still remain open or will this refresh the
page fully? I want to be able to have that modal dialog similar to an
iframe style where any actions that happen within the page in the
modal will still be there and be updated without the page having a
full refresh and the dialog closing.
The page will be refreshed fully with a normal form. To achieve what you describe, use an ajax form which does a post to a controller method and returns a partial view. Then have a success callback for the ajax form, which would replace the contents of a div (within the open dialog) with the response content (which would be the partial view returned from the post).
Simplified example...
View:
<div id="dialog-modal">
<p>Some optional static content here (within the dialog)
that should not change when the form is submitted.</p>
<div id="dialog-content">
#using (Html.BeginForm("MyAction", "MyController", null, FormMethod.Post, new { #id="MyForm" }))
{
#Html.EditorFor(x => x.Foo)
<input type="submit" value="OK" />
}
</div>
</div>
Controller:
[HttpPost]
public ActionResult MyAction(MyModel model)
{
// Do some stuff here with the model if you want
MyNewModel newModel = new MyNewModel();
return PartialView("_MyPartialView", newModel);
}
JavaScript:
$(function () {
$('#MyForm').submit(function () {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (xhr) {
$('#dialog-content').html(xhr);
}
});
return false;
});
});
Note that this implementation will replace the form, so you could put the form outside the div that gets replaced if needed, or have a different form in the partial view that gets returned if you want different forms submitted within the dialog in series. It's flexible to tweak to your needs. It also will not close the dialog until you explicitly call close on it, or affect any content outside of the replaced div's content. Hope this helps!

using SignalR with document onload instead of jquery onload

I have used the signalR chat app (as laid out in this tutorial http://sergiotapia.com/2011/09/signalr-with-mvc3-chat-app-build-asynchronous-real-time-persistant-connection-websites/) in a standalone test site and it all works great.
I'm now trying to incorporate it into my larger project.
Now unfortunately my larger project has a body onload function defined, so i don't use the standard jquery $(function () {}); syntax for executing stuff on page load. This hasn't been too much of an issue so far, most jquery plugins and scripts get executed in the function called by my body onload and its fine.
But for some reason, my signalR code just isn't executing.
Its the exact same code as laid out above, only its called on my body load.
The page loads, does a post to /signalr/negotiate (which returns the url and clientID)
In my sample app which works, it then does a continuous post to /signalr/connect
In my other app, it simply does a single get to the page im currently on.
Its not making the post to connect.
Is there a way to manually call this?
Here is the source of the page not working.
Please note that the reason im not referencing JQuery itself is because its loaded in my master page. JQuery is present.
<script src="/public/javascript/jquery.signalR.min.js">
<script src="/public/javascript/json2.js">
<script type="text/javascript" src="/signalr/hubs">
<div>
<input type="text" id="msg" />
<input type="button" id="broadcast" />
<ul id="messages"></ul>
</div>
<script type="text/javascript">
function ExecuteOnLoad() {
// Proxy created on the fly
var chat = $.connection.chat;
// Declare a function on the chat hub so the server can invoke it
chat.addMessage = function (message) {
$('#messages').append('<li>' + message + '</li>');
};
$("#broadcast").click(function () {
// Call the chat method on the server
chat.send($('#msg').val());
});
// Start the connection
$.connection.hub.start();
}
</script>
EDIT : here is the chat hub
public class Chat : SignalR.Hubs.Hub
{
public void Send(string message)
{
//Call the addMessage method on all clients.
Clients.addMessage(message);
}
}
DOUBLE EDIT : ok, i've made a standard html page in my mvc project and wired up the onload event again and everything works fine. the problem seems to be that polling doesn't seem to working when i call
$.connection.hub.start();
instead its doing a get to the current url and returning the page again in the get request.
The problem had nothing to do with the question I asked.
I thought it might have to do with the onload function, but it did not.
The problem was because my page had a reference to the Jquery.Validate plugin.
The version I was using was 1.7, I updated to 1.9 of the plugin and it worked fine.

Resources