I apologize ahead of time if this is something stupid like a semi-colon, but I'm having a hard time getting angular to recognize my controller (im a newbie to angular).
I get an error, Image Controller is undefined.
Notes: I am using the angular file upload plugin and this is a web api 2.0 application.
I have 2 Javascript files UniqueAPIStart, UniqueAPIImages
UniqueAPIStart(Fixed):
var UniqueAPI = angular.module('UniqueAPI', ['angularFileUpload']);
UniqueAPIImages(Fixed):
UniqueAPI.controller('ImageController', ['$scope', '$upload', function ($scope, $upload) {
$scope.$watch('myFiles', function() {
for (var i = 0; i < $scope.myFiles.length; i++) {
var file = $scope.myFiles[i];
$scope.upload = $upload.upload({
url: '/api/AdminImages', // upload.php script, node.js route, or servlet url
//method: 'POST' or 'PUT',
//headers: {'Authorization': 'xxx'}, // only for html5
//withCredentials: true,
data: { myObj: $scope.myModelObj },
file: file, // single file or a list of files. list is only for html5
//fileName: 'doc.jpg' or ['1.jpg', '2.jpg', ...] // to modify the name of the file(s)
//fileFormDataName: myFile, // file formData name ('Content-Disposition'), server side request form name
// could be a list of names for multiple files (html5). Default is 'file'
//formDataAppender: function(formData, key, val){} // customize how data is added to the formData.
// See #40#issuecomment-28612000 for sample code
}).progress(function(evt) {
console.log('progress: ' + parseInt(100.0 * evt.loaded / evt.total) + '% file :' + evt.config.file.name);
}).success(function(data, status, headers, config) {
// file is uploaded successfully
alert('file ' + config.file.name + 'is uploaded successfully. Response: ' + data);
}).error(function (data, status) {
alert(data.error);
});
//.then(success, error, progress); // returns a promise that does NOT have progress/abort/xhr functions
//.xhr(function(xhr){xhr.upload.addEventListener(...)}) // access or attach event listeners to
//the underlying XMLHttpRequest
}
/* alternative way of uploading, send the file binary with the file's content-type.
Could be used to upload files to CouchDB, imgur, etc... html5 FileReader is needed.
It could also be used to monitor the progress of a normal http post/put request.
Note that the whole file will be loaded in browser first so large files could crash the browser.
You should verify the file size before uploading with $upload.http().
*/
// $scope.upload = $upload.http({...}) // See 88#issuecomment-31366487 for sample code.
});
}]);
And then my cshtml:
#section scripts
{
<script type="text/javascript" src ="/Scripts/API/ImageController.js"></script>
}
<div class="container" ng-app="UniqueAPI">
<div class="row">
<div class="col-md-4" ng-controller="ImageController">
<form action="javascript:void(0);">
<div class="form-group">
<label for="imgDescription">Email address</label>
<input type="text" class="form-control" id="imgDescription" placeholder="Image Description">
<button ng-file-select ng-model="files" multiple="true">Attach Any File</button>
<div ng-file-drop ng-model="files" class="drop-box"
drag-over-class="{accept:'dragover', reject:'dragover-err', delay:100}"
multiple="true" allow-dir="true" accept="image/*">
Drop Images here
</div>
</div>
</form>
</div>
</div>
</div>
LayoutFile:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>#ViewBag.Title</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home", new { area = "" }, null)</li>
<li>#Html.ActionLink("API", "Index", "Help", new { area = "" }, null)</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
<script type="text/javascript" src="~/Scripts/angular-file-upload-all.js"></script>
<script type="text/javascript" src="~/Scripts/angular-file-upload-shim.js"></script>
<script type="text/javascript" src="~/Scripts/angular-file-upload.js"></script>
<script type="text/javascript" src="~/Scripts/API/UniqueAPIStart.js"></script>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
First of all I could't see you importing the required libraries:
<script src="https://angular-file-upload.appspot.com/js/angular-file-upload-shim.js"></script>
<script src="https://angular-file-upload.appspot.com/js/angular-file-upload.js"></script>
and. You are creating the module twice:
var UniqueAPI = angular.module('UniqueAPI', []);
angular.module('UniqueAPI', ['angularFileUpload']);
It should be something like this
var UniqueAPI = angular.module('UniqueAPI', ['angularFileUpload']);
Related
I am having this issue with my home button not adding headers in a get request. I have stored a token inside of the localStorage and I send it in the headers when I make a get request to Controller: Home Action: Index. From what I see, it doesn't use my jquery and goes straight to the Account/Index.
Initially, I though it was a problem with the javascript not binding to a button click. After further investigation, I found that the Console.log() I have in _Layout.cshtml do not work and neither does the button. This leads me to believe there is a problem with $("html").html(response); in the Login.js file.
The correct flow is LoginPage -> Login.js (grabs data and uses Ajax for a post request.) -> Returns a html page composing of _Layout.cshtml and /Views/Home/Index.cshtml
Below is my code for the file "Views/Shared/_Layout.cshtml":
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>#ViewData["Title"] - Chat </title>
<environment include="Development">
<link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="~/css/site.css" />
</environment>
<environment exclude="Development">
<link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css"
asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute" />
<link rel="stylesheet" href="~/css/site.min.css" asp-append-version="true" />
</environment>
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li id="li_btnHome"><a asp-area="" asp-controller="" asp-action="">Home</a></li>
</ul>
</div>
</div>
</nav>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© 2018 - Chat</p>
</footer>
</div>
<environment include="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js" asp-append-version="true"></script>
<script type="text/javascript">
console.log("Development");
</script>
</environment>
<environment exclude="Development">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-3.3.1.min.js"
asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
asp-fallback-test="window.jQuery"
crossorigin="anonymous"
integrity="sha384-tsQFqpEReu7ZLhBV2VZlAu7zcOV+rXbYlF2cqB8txI/8aZajjp4Bqd+V6D5IgvKT">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/bootstrap.min.js"
asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.min.js"
asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
crossorigin="anonymous"
integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa">
</script>
<script src="~/js/site.min.js" asp-append-version="true"></script>
<script type="text/javascript">
console.log("Not Development");
</script>
</environment>
<script type="text/javascript">
console.log("Hello World");
</script>
<!--<script src="~/js/NavBarFunction.js"></script>-->
#RenderSection("Scripts", required: false)
</body>
</html>
Here's the javascript file "wwwroot/js/NavBarFunctions.js":
$("#li_btnHome a")[0].onclick = function (event) {
event.preventDefault();
alert("called click");
var tokenObj = localStorage.getItem("token");
var tokenStr = tokenObj == null ? "what_about_tokenObj_is_null?" : tokenObj.toString();
$.ajax({
type: 'GET',
contentType: 'application/json; charset=utf-8;',
url: '#Url.Action("Index", "Home")',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", tokenStr);
},
success: function (response) {
alert(1);
$("html").html(response);
}
});
return false;
};
Here's the HomeController, located in "Controllers/HomeController":
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Chat.Enums;
using Chat.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
namespace _Chat.Controllers
{
public class HomeController : Controller
{
private AuthenticateUser authenticateUser = new AuthenticateUser();
public async Task<IActionResult> Index()
{
var request = Request;
var headers = request.Headers;
StringValues token;
if (headers.TryGetValue("Authorization", out token))
{
var result = await this.authenticateUser.ValidateToken(token);
if (result.Result == AuthenticateResult.Success)
{
return View();
}
else
{
return RedirectToAction("Index", "Account");
}
}
return RedirectToAction("Index", "Account");
}
}
}
For some odd reason, it looks like after my page is redirected from log in to home, all scripts/javascript stop working.
Here's the code authenticating login. Located in "Controllers/AccountController":
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Chat.Models;
using Chat.DatabaseAccessObject;
using Chat.Identity;
using Chat.DatabaseAccessObject.CommandObjects;
using System.Linq.Expressions;
using System.Net.Mime;
using System.Security.Claims;
using System.Text;
using Microsoft.AspNetCore.Authentication;
using Microsoft.IdentityModel.Tokens;
namespace Chat.Controllers
{
public class AccountController : Controller
{
private const string SECRET_KEY = "CHATSECRETKEY";
public static SymmetricSecurityKey SIGNING_KEY = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SECRET_KEY));
private ServerToStorageFacade serverToStorageFacade = new ServerToStorageFacade();
private AuthenticateUser authenticateUser = new AuthenticateUser();
public IActionResult Index()
{
return View();
}
// Post: /login/
[HttpPost]
public async Task<IActionResult> Login([FromBody]LoginModel loginModel)
{
if (ModelState.IsValid)
{
var mapLoginModelToUser = new MapLoginModelToUser();
var user = await mapLoginModelToUser.MapObject(loginModel);
// If login user with those credentials does not exist
if(user == null)
{
return BadRequest();
}
else
{
var result = await this.authenticateUser.Authenticate(user);
if(result.Result == Chat.Enums.AuthenticateResult.Success)
{
// SUCCESSFUL LOGIN
// Creating and storing cookies
var token = Json(new
{
data = this.GenerateToken(user.Email, user.PantherID),
redirectUrl = Url.Action("Index","Home"),
success = true
});
return Ok(token);
}
else
{
// Unsuccessful login
return Unauthorized();
}
}
}
return BadRequest();
}
private string GenerateToken(string email, string pantherId)
{
var claimsData = new[] { new Claim(ClaimTypes.Email, email), new Claim(ClaimTypes.Actor, pantherId) };
var signInCredentials = new SigningCredentials(SIGNING_KEY, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: "localhost",
audience: "localhost",
expires: DateTime.Now.AddDays(7),
claims: claimsData,
signingCredentials: signInCredentials
);
return new JwtSecurityTokenHandler().WriteToken(token);
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public async Task<IActionResult> Error() => View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
public class MapLoginModelToUser
{
private ServerToStorageFacade serverToStorageFacade;
public MapLoginModelToUser()
{
serverToStorageFacade = new ServerToStorageFacade();
}
public async Task<User> MapObject(LoginModel loginModel)
{
Expression<Func<User, bool>> expression = x => x.Email == loginModel.inputEmail;
var user = await this.serverToStorageFacade.ReadObjectByExpression(new User(Guid.NewGuid()), expression);
if(user == default(Command))
{
return null;
}
return new User(user.ID)
{
Email = loginModel.inputEmail,
Password = loginModel.inputPassword,
FirstName = user.FirstName,
LastName = user.LastName,
PantherID = user.PantherID,
ClassDictionary = user.ClassDictionary,
UserEntitlement = user.UserEntitlement
};
}
}
}
Also the code that renders the page. Located in "wwwroot/js/Login.js":
$(document).ready(function () {
$("#formSubmit").submit(function (event) {
event.preventDefault();
var email = $("#inputEmail").val();
var password = $("#inputPassword").val();
var remember = $("#rememberMe").val();
var loginModel = {
inputEmail: email,
inputPassword: password,
rememberMe: remember
};
$.ajax({
type: 'POST',
url: 'Account/Login',
data: JSON.stringify(loginModel),
contentType: 'application/json; charset=utf-8;',
success: function (response) {
var token = response.value.data;
localStorage.setItem("token", token);
alert("You have successfully logged in.");
setHeader();
redirect(response.value.redirectUrl);
}
});
});
function setHeader() {
$.ajaxSetup({
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', localStorage.getItem("token"));
}
});
}
function redirect(redirectUrl) {
$.ajax({
type: 'GET',
contentType: 'application/json; charset=utf-8;',
url: redirectUrl,
success: function (response) {
$("html").html(response);
}
});
}
});
This is the error received after loading the new html page:
EDIT: This is what's sent in the response after the Home button is clicked.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Login - Chat FIU</title>
<link rel="stylesheet" href="/lib/bootstrap/dist/css/bootstrap.css" />
<link rel="stylesheet" href="/css/site.css" />
</head>
<body>
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a id="btnHome" href="/">Home</a></li>
</ul>
</div>
</div>
</nav>
<div class="container body-content">
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous">
<link href="/css/signin.css" rel="stylesheet">
<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="/js/Login.js"></script>
</head>
<body class="text-center">
<form id="formSubmit" method="post" class="form-signin">
<img class="mb-4" src="/images/FIU-Chat-Curved.png" alt="" width="150" height="150">
<h1 class="h3 mb-3 font-weight-normal">Please sign in</h1>
<label for="inputEmail" class="sr-only">Email address</label>
<input autofocus="" class="form-control" data-val="true" data-val-required="The Email field is required." id="inputEmail" name="inputEmail" placeholder="Email address" required="required" type="email" value="" />
<label for="inputPassword" class="sr-only">Password</label>
<input class="form-control" data-val="true" data-val-required="The Password field is required." id="inputPassword" name="inputPassword" placeholder="Password" required="required" type="password" />
<div class="checkbox mb-3">
<label>
<input data-val="true" data-val-required="The Remember field is required." id="rememberMe" name="rememberMe" type="checkbox" value="true" /> Remember me
</label>
</div>
<button id="btnLogin" class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
<p class="mt-5 mb-3 text-muted">© 2017-2018</p>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8Ah5tOyN_3lPrH0DgSEU8vD7Q7JItdizW-mYDc5uamCO3oRTBN-pdo9ZyPgRaHRyovwEGfT5Qhw0UD-rfbIHUJPt4FgUOhM1OkAWC9AtAfPEKkxz7TBfwKfz0EpfxF4DX2DAczujogr__xnIr3vDq3o" /><input name="rememberMe" type="hidden" value="false" /></form>
</body>
</html>
<hr />
<footer>
<p>© 2018 - Chat FIU</p>
</footer>
</div>
<script src="/lib/jquery/dist/jquery.js"></script>
<script src="/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="/js/site.js?v=BxFAw9RUJ1E4NycpKEjCNDeoSvr4RPHixdBq5wDnkeY"></script>
<script type="text/javascript">
</script>
<script type="text/javascript">
</script>
<script src="/js/NavBarFunction.js"></script>
</body>
The key to solve the problem is in your flow described here:
The correct flow is LoginPage -> Login.js (grabs data and uses Ajax
for a post request.) -> Returns a html page composing of
_Layout.cshtml and /Views/Home/Index.cshtml
This kind of flow implies that you want to redirect into index page (proved by usage of return RedirectToAction("Index", "Account"); in controller action), which AJAX usage in redirection with GET method makes no sense (because AJAX call intended to stay in the same page).
Instead of replacing entire HTML page content using $("html").html(response);, use window.location.href to redirect with specified URL like this:
NavBarFunctions.js
$("#li_btnHome a")[0].click(function (event) {
event.preventDefault();
alert("called click");
var tokenObj = localStorage.getItem("token");
var tokenStr = tokenObj == null ? "what_about_tokenObj_is_null?" : tokenObj.toString();
$.ajax({
type: 'GET',
url: '#Url.Action("Index", "Home")',
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", tokenStr);
},
success: function (response) {
// this is just an example, replace action & controller name as you wish
window.location.href = '#Url.Action("ActionName", "ControllerName")';
}
});
});
Login.js
function redirect(redirectUrl) {
$.ajax({
type: 'GET',
contentType: 'application/json; charset=utf-8;',
url: redirectUrl,
success: function (response) {
window.location.href = redirectUrl;
}
});
}
However if you want to render certain portion of the page using partial view, you may use jQuery.html() targeting a placeholder, e.g. <div> tag:
<!-- partial view placeholder -->
<div id="content">...</div>
// ajax callback
$.ajax({
// other settings
.....
success: function (response) {
$('#content').html(response);
},
.....
});
I tried to implement Signalr notification to my existing MVC project and my code in the View as follows
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - My ASP.NET Application</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<span class="noti glyphicon glyphicon-bell"><span class="count"> </span></span>
<div class="noti-content">
<div class="noti-top-arrow"></div>
<ul id="notiContent"></ul>
</div>
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
#Html.ActionLink("Application name", "Index", "Home", new { area = "" }, new { #class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
<li>#Html.ActionLink("Contact", "Contact", "Home")</li>
</ul>
#Html.Partial("_LoginPartial")
</div>
</div>
</div>
<div class="container body-content">
#RenderBody()
<hr />
<footer>
<p>© #DateTime.Now.Year - My ASP.NET Application</p>
</footer>
</div>
#* Add Jquery Library *#
<script src="~/Scripts/jquery-2.2.3.min.js"></script>
<script src="~/Scripts/jquery.signalR-2.2.0.min.js"></script>
<script src="/signalr/hubs"></script>
<script src="~/Scripts/bootstrap.min.js"></script>
#* Add css *#
<link href="~/Content/bootstrap.min.css" rel="stylesheet" />
<style type="text/css">
/*Added css for design notification area, you can design by your self*/
/* COPY css content from youtube video description*/
</style>
#* Add jquery code for Get Notification & setup signalr *#
<script type="text/javascript">
$(function () {
// Click on notification icon for show notification
$('span.noti').click(function (e) {
e.stopPropagation();
$('.noti-content').show();
var count = 0;
count = parseInt($('span.count').html()) || 0;
//only load notification if not already loaded
if (count > 0) {
updateNotification();
}
$('span.count', this).html(' ');
})
// hide notifications
$('html').click(function () {
$('.noti-content').hide();
})
// update notification
function updateNotification() {
$('#notiContent').empty();
$('#notiContent').append($('<li>Loading...</li>'));
$.ajax({
type: 'GET',
url: '/home/GetNotificationContacts',
success: function (response) {
$('#notiContent').empty();
if (response.length == 0) {
$('#notiContent').append($('<li>No data available</li>'));
}
$.each(response, function (index, value) {
$('#notiContent').append($('<li>New contact : ' + value.ContactName + ' (' + value.ContactNo + ') added</li>'));
});
},
error: function (error) {
console.log(error);
}
})
}
// update notification count
function updateNotificationCount() {
var count = 0;
count = parseInt($('span.count').html()) || 0;
count++;
$('span.count').html(count);
}
// signalr js code for start hub and send receive notification
var notificationHub = $.connection.notificationHub;
$.connection.hub.start().done(function () {
console.log('Notification hub started');
});
//signalr method for push server message to client
notificationHub.client.notify = function (message) {
if (message && message.toLowerCase() == "added") {
updateNotificationCount();
}
}
})
</script>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</body>
</html>
In the Line
// signalr js code for start hub and send receive notification
var notificationHub = $.connection.notificationHub;
$.connection.hub.start().done(function () {
console.log('Notification hub started');
});
$.connection does not have a definition
and When running the application
Uncaught TypeError: Cannot read property 'notificationHub' of undefined
at HTMLDocument.<anonymous> (Login:219)
at i (jquery-2.2.3.min.js:2)
at Object.fireWith [as resolveWith] (jquery-2.2.3.min.js:2)
at Function.ready (jquery-2.2.3.min.js:2)
at HTMLDocument.J (jquery-2.2.3.min.js:2)
It shows the error line as
var notificationHub = $.connection.notificationHub;
But when I tried to implement in a new project it worked after removing some additional scripts references, but in this project it did not worked
Here is the example I followed
http://www.dotnetawesome.com/2016/05/push-notification-system-with-signalr.html
This works fine for empty MVC project but when trying to implement the same to existing one gives this issue.
// signalr js code for start hub and send receive notification var notificationHub = $.connection.notificationHub;
$.connection does not have a definition which should come from jquery.signalR-2.2.0.js
Any idea to solve this issue
i'm also developing a project with signalr and i guess also that this is a referencing problem.
Look at your code again, the line:
<script src="~/Scripts/jquery-2.2.3.min.js"></script>
and the line:
#Scripts.Render("~/bundles/jquery")
Here you are referencing your jQuery libraries 2 times. I would refactor the referencing and keep it only in one place and before the signalr code. Because signalr depends on jquery library. I suggest you to go with this hierarchy:
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/bootstrap")
#Scripts.Render("~/bundles/jqueryTables")
<script src="~/signalr/hubs"></script>
#RenderSection("scripts", required: false)
Hope it helps. Let me know it you have any question!!
I am pretty new to web programming specially javascript and other front end logic. I am seeing this weird error where my code works perfectly fine on latest version of Firefox on Windows 10 but does not work on latest version of chrome on Windows 10.
Basically I have a form which consists of two multi select drop down and two buttons. For both these buttons, I send ajax POST request in their click listener with checkbox params to python flask server which in turn creates a file on the server then in success of my POST ajax, I send get request to download the file that I just created. In Firefox and chrome both, my POST calls are going and files are being generated correctly, however get request is not sent by chrome to download the file but firefox is sending correct get request to get the file.
Another weird thing is, chrome does download a file upon get request which it is sending somewhere but it is not reaching my server. I do not see get request in my flask server log from chrome but it does show up for firefox. In both cases files are downloaded but chrome downloads wrong file from some wrong place.
I also tried adding delay on server thinking, file is still being generated when POST request is returned but that also didn't change chrome behaviour.
Below is the snippet of my code.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="shortcut icon" type="image/x-icon" href="static/images/main.png">
<title>Link Curation - Curated Results</title>
<!-- Scripts-->
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="static/js/materialize.js"></script>
<script src="static/js/init.js"></script>
<!-- CSS -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="static/css/materialize.css" type="text/css" rel="stylesheet" media="screen"/>
<link href="static/css/style.css" type="text/css" rel="stylesheet" media="screen"/>
<script>
$(document).ready(function(){
$('#progress').hide();
$('select').material_select();
// Download jsonlines
$("#jlines").click(function(e){
// Required for non-chrome browser
e.preventDefault()
var tags = $('#museums').val();
var codes = $('#codes').val();
var userObj = new Object();
userObj.data = {"tags":tags,"codes":codes,"type":"jlines"};
json_data = JSON.stringify(userObj);
console.log(json_data);
var sv = '{{server}}'.concat("/download");
$.ajax({
method: 'POST',
url: sv,
data: json_data,
contentType: 'application/json',
beforeSend: function(){
$('#progress').show();
document.getElementById("jlines").disabled = true;
console.log("downloading...")
},
success: function(data){
console.log("File Created!");
$('#progress').hide();
document.getElementById("jlines").disabled = false;
window.location.href = "/download?type=jlines";
},
error: function(xhr){
console.log('Request Status: ' + xhr.status + ' \nStatus Text: ' + xhr.statusText + ' \nResponse Text: ' + xhr.responseText);
Materialize.toast("Something went wrong. Please try again!",5000);
$('#progress').hide();
document.getElementById("jlines").disabled = false;
}
});
});
// Download triples
$("#triples").click(function(e){
// Required for non-chrome browser
e.preventDefault()
var tags = $('#museums').val();
var codes = $('#codes').val();
var userObj = new Object();
userObj.data = {"tags":tags,"type":"triples"};
json_data = JSON.stringify(userObj);
console.log(json_data);
var sv = '{{server}}'.concat("/download");
$.ajax({
method: 'POST',
url: sv,
data: json_data,
contentType: 'application/json',
beforeSend: function(){
$('#progress').show();
document.getElementById("triples").disabled = true;
console.log("downloading...")
},
success: function(data){
console.log("File Created!");
$('#progress').hide();
document.getElementById("triples").disabled = false;
window.location.href = "/download?type=triples";
},
error: function(xhr){
console.log('Request Status: ' + xhr.status + ' \nStatus Text: ' + xhr.statusText + ' \nResponse Text: ' + xhr.responseText);
Materialize.toast("Something went wrong. Please try again!",5000);
$('#progress').hide();
document.getElementById("triples").disabled = false;
}
});
});
});
</script>
<style>
#body {
min-height: calc(100vh - 10px);
}
</style>
</head>
<body>
<div>{% include 'header.html' %}</div>
<div id="body">
<div class="section no-pad-bot" id="index-banner">
<div class="container">
<div class="row center">
<br><br>
<h5> Download the curated results (Tip: Select ulan to download all data!) </h5>
<br><br>
<div class="header col s12 m4">
<select multiple id="museums" >
<option value="" disabled selected>Choose museum(s)</option>
{% for tag in keys %}
<option value={{tag}}>{{tag}}</option>
{% endfor %}
</select>
</div>
<div class="header col s12 m4">
<select multiple id="codes">
<option value="" disabled selected>Choose pair status(s)</option>
<option value="3">Match</option>
<option value="4">Unmatch</option>
<option value="5">Not Sure</option>
</select>
</div>
<div class="header col s12 m4">
<form name ="download_data">
<div id="progress" class="preloader-wrapper small active">
<div class="spinner-layer spinner-green-only">
<div class="circle-clipper left">
<div class="circle"></div>
</div>
<div class="gap-patch">
<div class="circle"></div>
</div>
<div class="circle-clipper right">
<div class="circle"></div>
</div>
</div>
</div>
<button id = "jlines" type="submit" class="btn" >Jsonlines</button>
<button id = "triples" type="submit" class="btn" >Triples</button>
</form>
</div>
</div>
</div>
</div>
<div class="section no-pad-bot">
<div class="container">
<div class="row center">
<h5>Curated results from all museums will show up below. You can sort them based on the status or URI or even search based on museum.</h5>
<br><br>
<iframe class="header col s12 light" src="datatable" style="border:0" height="1000" ></iframe>
</div>
</div>
</div>
</div>
<div>{% include 'footer.html' %}</div>
</body>
</html>
Thanks for the help.
Nilay
I'm building a sample application with YouTube API (v3), that would provide a list of videos based on a search term. The concept is to populate the page using the data from the response.
I have used the client library documented in v3 to access the API, and send my request, however I don't know how to properly navigate through the data provided in the response in order to display the desired elements. The code below shows my script, where I am trying to access and list the title of the videos in the response:
$(function () {
//FUNCTION TO COLLECT QUERY TERM FROM SEARCH FORM
var $searchField = $('#search-text');
$('#mainSearch'). on ('submit', function(e){
e.preventDefault();
if ($searchField.val() !== '') { //IF SEARCH FORM IS NOT EMPTY
var $searchQuery = $searchField.val()+ ' parody'; //PREPARE SEARCH QUERY
makeRequest($searchQuery); //PASS SEARCH QUERY TO REQUEST FUNCTION
}
else {
$searchField.focus(); //ADD ERROR CLASS HERE
$searchField.blur(function (e){
//REMOVE ERROR CLASS HERE
});
}
});
function makeRequest(query){
var request = gapi.client.youtube.search.list({
part: 'snippet',
q: query
});
$('.content').empty();
request.execute(parseResponse);
}
function parseResponse(data) {
$.each(data, function (i, items){
var $infoDiv = $('<div></div>');
$infoDiv.append('<p>'+ items.snippet.title +'</p>');
$('.content').append($infoDiv);
});
}
});
//LOAD API CLIENT
function initClient() {
gapi.client.load('youtube', 'v3');
gapi.client.setApiKey('AIzaSyARVmOp3tBIA3ZgW6z4DK_-1sMJwulPvps');
}
However my page does get not populated with any data, and I get this error in my console:
Uncaught TypeError: Cannot read property 'title' of undefined
And here is the markup for my page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Parrdy Template</title>
<!--
<Bootstrap></Bootstrap>-->
<link href="stylesheets/bootstrap.min.css" rel="stylesheet"/>
<link href="stylesheets/style.min.css" rel="stylesheet"/>
<!--
<HTML5>Shim and Respond.js IE8 support of HTML5 elements and media queries </HTML5>--><!--
<WARNING>
<Respond class="js">doesn't work if you view the page via file:// </Respond>
</WARNING>--><!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script><![endif]-->
</head>
<body>
<div class="container">
<div class="header">
<img src="/images/Logo1_mod.png" width="200">
<form role="form" id= "mainSearch" class="navbar-form navbar-right pull-right">
<div class="form-group">
<input type="text" id="search-text" placeholder="Search" class="form-control">
</div>
<button type="submit" id="vid-search" class="btn btn-sm btn-warning">Search</button>
</form>
</div>
{{{body}}}
<div class="footer">
<ul class="nav nav-pills pull-left">
<li><a class="customcolor" href="#">About</a></li>
<li><a class="customcolor" href="#">Contact Us</a></li>
</ul>
</div>
</div><!--container ends-->
<!--
<jQuery>(necessary for Bootstrap's JavaScript plugins) </jQuery>-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script><!--
<Include>all compiled plugins (below), or include individual files as needed</Include>-->
<script src="js/bootstrap.min.js"></script>
<script src="js/core1.1.js"></script>
<script src="https://apis.google.com/js/client.js?onload=initClient" type="text/javascript">
</script>
</body>
</html>
Any help on how to access the elements correctly from a YouTube API response would be appreciated. Thanks.
The first thing you'll want to keep in mind is that the stuff you are after is nested in the response as data so you need to access 'response.data' and within that data is an array of items. You'll want to access the first array with items[0] now you can grab the id from here or go deeper with .snippet or .statistic
get(url)
.then(response => {
id: response.DATA.items[0].id
title: response.DATA.items[0].snippet.title
}
.catch(
error => {console.log(error)}
You should change your loop like this:
$.each(data.videos, function (i, items){
var $infoDiv = $('<div></div>');
$infoDiv.append('<p>'+ items.snippet.title +'</p>');
$('.content').append($infoDiv);
});
I am new to Angular.js and i did the tutorial Shaping up with angularjs in codeschool.com so please forgive me if the problem i am trying to solve might be too easy to resolve.
So, i am just trying to show a data i get from $http.get() which is JSON object into my document.
index.html:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>League of legends</title>
<!-- Load StyleSheets -->
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">
<!-- Load Javascript Libraries -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/angular.min.js"></script>
<script type="text/javascript" src="js/app.js"></script>
</head>
<body ng-app="LeagueOfLegends">
<!-- Navbar menu -->
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li>
About
</li>
<li>
Contact
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div ng-controller="searchSummoner as summoner">
<!-- Search Form -->
<div ng-show="summoner.status.showSearch">
<form ng-submit="summoner.search()">
<div class="well">
<div class="form-group">
<label for="summonerName">Summoner Name</label>
<input type="text" class="form-control" placeholder="Enter Summoner Name" id="summonerName" ng-model="summoner.form.name">
</div>
<div class="form-group">
<label ng-repeat="region in summoner.region">
<input type="radio" ng-model="summoner.form.region" ng-value="region">{{region}}
</label>
</div>
<input type="submit" class="btn btn-default" value="Search"></input>
</div>
</form>
</div>
<p ng-show="summoner.status.showResult">Get request from: {{summoner.data.name}}</p>
</div>
</div>
</body>
app.js (module-controller):
var app = angular.module('LeagueOfLegends', []);
app.controller('searchSummoner', ['$http', function($http)
{
var form = {};
this.data = {};
this.form = {};
this.status = {
showSearch: true,
showResult: false
};
this.region = ['br', 'eune', 'euw', 'lan', 'las', 'na', 'oce', 'kr', 'tr'];
this.search = function()
{
form = this.form;
this.form = {};
// get data from the api rest
$http.get(getApiUrl(form)).success(function(data){
this.data = data[form.name];
console.log(this.data);
});
// hide form
this.status.showSearch = false;
this.status.showResult = true;
};
}]);
function getApiUrl(form)
{
var apiKey = 'fe9eb24f-5800-4f2a-b570-15328062b341';
return 'https://lan.api.pvp.net/api/lol/' + form.region + '/v1.4/summoner/by-name/' + form.name + '?api_key=fe9eb24f-5800-4f2a-b570-15328062b341'
}
after $http.get was successfully made, i make a log just to check if the data i retrieve is the one i need, but it does not show the object property in html
You're using this in the wrong closure. This is what you should do :
var that = this;//give controller scope access
// get data from the api rest
$http.get(getApiUrl(form)).success(function(data){
that.data = data[form.name];
console.log(that.data);
});
You could also bind your context like this:
$http.get(getApiUrl(form)).success(function(data){
this.data = data[form.name];
console.log(this.data);
}.bind(this));
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind