I'm running a Node server with express which renders jade. I'm trying to make my client side use knockout.js but the view never updates... I don't get any errors in the console and I just can't figure out what is wrong.
Page:
extends layout
block content
script(src='knockout/knockout-2.2.1.debug.js', type='text/javascript')
script(src='js/app.js', type='text/javascript')
p Hi,
strong(data-bind="text: firstName")
rendered html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="/stylesheets/style.css">
</head>
<body>
<script src="knockout/knockout-2.2.1.debug.js" type="text/javascript"></script>
<script src="js/app.js" type="text/javascript"></script>
<p>Hi,<strong data-bind="text: firstName"></strong></p>
</body>
</html>
app.js:
function AppViewModel() {
this.firstName = ko.observable("Bert");
this.lastName = ko.observable("Bertington");
}
ko.applyBindings(new AppViewModel());
is there something I'm missing here or is it just not possible to make this happen with Node.js and express?
You need to make sure you call ko.applyBindings() after the DOM has already been loaded.
Either wrap the code in app.js in window.onload, in jQuery's ready() function, or move your script tag to be below <p>Hi,<strong data-bind="text: firstName"></strong></p>.
// this is my js file
(function () {
//START THE APP WHEN DOCUMENT IS READY
$(function () {
function AppViewModel() {
var self = this;
self.firstName = "Hamza";
// self.lastName = ko.observable("Bertington");
}
ko.applyBindings(new AppViewModel());
});
})();
Related
I know this question was asked before, but my question is about using abp.services methods in JavaScript directly.
Suppose I have:
public interface ISecurityAppService : IApplicationService
{
List<PacsUser_C_Extented> GetAll();
}
public class SecurityAppService : ApplicationService, ISecurityAppService
{
public List<PacsUser_C_Extented> GetAll()
{
// ...
return allUsers;
}
}
All the boilerplate services will be registered nicely as:
public class Global : AbpWebApplication<ImmenseWebModule>
{
protected override void Application_Start(object sender, EventArgs e)
{
base.Application_Start(sender, e);
}
}
As the ASP.NET Boilerplate documentation said, to be able to use the auto-generated services, you should include needed scripts in your page like:
<script src="~/Abp/Framework/scripts/libs/angularjs/abp.ng.js"></script>
<script src="~/api/AbpServiceProxies/GetAll?type=angular"></script>
I know the second line says to use angular controller, but I change it to:
<script src="~/api/AbpServiceProxies/GetAll?v=#(Clock.Now.Ticks)">script>
...still nothing works.
When I want to use getAll in an ASP.NET Web Form's JavaScript code, it gives me:
abp.service is not defined
So how can I use getAll or another method in SecurityAppService in the script element <script>...</script> — not Angular?
Thanks in advance.
Update
When I use an Angular controller and MVC partial view like:
(function () {
var app = angular.module('app');
var controllerId = 'sts.views.security.list';
app.controller(controllerId, [
'$scope', 'abp.services.remotesystem.security',
function ($scope, securityService) {
var vm = this;
vm.localize = abp.localization.getSource('ImmenseSystem');
vm.users = [];
vm.refreshUserList = function () {
abp.ui.setBusy( // Set whole page busy until getTasks completes
null,
securityService.getAll().success(function (data) {
vm.users = data;
abp.notify.info(vm.localize('UserListLoaded'));
})
);
};
vm.refreshUserList();
}
]);
})();
I am able to use that function.
But I want to use that in JavaScript in ASP.NET Web Form pages.
Finally I resolved it by a simple way as the below steps...
1- Run project and use that boilerplate services by Angular and Partial view (MVC)
like Update section in question.
2- After running and redirecting to a view, I went to View page source and see the dependencies scripts .
3- I copied the below scripts source to a page:
<script src="Scripts/jquery-2.2.0.min.js"></script>
<script src="Scripts/jquery-ui-1.11.4.min.js"></script>
<script src="Scripts/jquery.validate.min.js"></script>
<script src="Scripts/modernizr-2.8.3.js"></script>
<script src="Abp/Framework/scripts/utils/ie10fix.js"></script>
<script src="Scripts/json2.min.js"></script>
<script src="Scripts/bootstrap.min.js"></script>
<script src="Scripts/moment-with-locales.min.js"></script>
<script src="Scripts/jquery.blockUI.js"></script>
<script src="Scripts/toastr.min.js"></script>
<script src="Scripts/sweetalert/sweet-alert.min.js"></script>
<script src="Scripts/others/spinjs/spin.js"></script>
<script src="Scripts/others/spinjs/jquery.spin.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-animate.min.js"></script>
<script src="Scripts/angular-sanitize.min.js"></script>
<script src="Scripts/angular-ui-router.min.js"></script>
<script src="Scripts/angular-ui/ui-bootstrap.min.js"></script>
<script src="Scripts/angular-ui/ui-bootstrap-tpls.min.js"></script>
<script src="Scripts/angular-ui/ui-utils.min.js"></script>
<script src="Abp/Framework/scripts/abp.js"></script>
<script src="Abp/Framework/scripts/libs/abp.jquery.js"></script>
<script src="Abp/Framework/scripts/libs/abp.toastr.js"></script>
<script src="Abp/Framework/scripts/libs/abp.blockUI.js"></script>
<script src="Abp/Framework/scripts/libs/abp.spin.js"></script>
<script src="Abp/Framework/scripts/libs/abp.sweet-alert.js"></script>
<script src="Abp/Framework/scripts/libs/angularjs/abp.ng.js"></script>
<script src="Scripts/jquery.signalR-2.2.1.min.js"></script>
<script src="api/AbpServiceProxies/GetAll?v=636475780135774228"></script>
<script src="api/AbpServiceProxies/GetAll?type=angular&v=636475780135774228"></script>
<script src="AbpScripts/GetScripts?v=636475780135774228" type="text/javascript"></script>
and use getAll method like:
<script>
var securityService = abp.services.remotesystem.security;
securityService.getAll().done(function (data) {
for (var i in data)
console.log(data[i].username);
});
</script>
I think the important staff to use auto-generated services is :
<script src="api/AbpServiceProxies/GetAll?v=636475780135774228"></script>
<script src="api/AbpServiceProxies/GetAll?type=angular&v=636475780135774228"></script>
<script src="AbpScripts/GetScripts?v=636475780135774228" type="text/javascript"></script>
Thanks for your attention.
you are injecting abp.services.remotesystem.security.
so you can use this namespace to access the functions. open chrome console and write abp.services.remotesystem.security you will see the functions
AssetApplicationService must be implemented by IApplicationService and then check your module load correctly and add correct dependencies in other modules like this.
Check this link. It's worked for me.
I wrote a JS plugin to client's website can load comments from our database via CORS method.
My goal is to wrapper my whole code into an easily embeddable plugin.
Just like the facebook js plugin, Google Analytics plugin. They are easy to install on a website.
My plugin depends on other libraries, such as jquery, underscore, backbone, handlebars, and also my scripts and CSS.
I studied Require.js it seems suitable to do this job for me.
I need to generate an all-in-one javascript plugin, e.g.,. "awesome-comments.min.js".
Some articles suggest me to put all the dependent js files with require.config.
But I'm having no idea how could I do other stuff such as my js scripts with require.js.
Is there any similar application or tutorial has the same function. Thanks.
sample_with_requireJS.html
<html>
<head>
<script src="js/require.js" data-main="js/main"></script>
</head>
<body>
<div id="load_awesome_comments"></div>
</body>
</html>
js/main.js
require.config({
baseUrl: "http://mywebsite/assets/",
paths: {
"jquery": "jquery-9e7b5a8e0157d7776b987d8963c9c786.js?body=1",
"underscor": "~~~",
...
}
});
sample-without-requireJS.html (This is my current workable html sample, mixed with js, css and html DOM)
<html>
<head>
<meta charset="utf-8">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.1.2/backbone-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"/>
<script src="http://localhost:3001/assets/jquery-9e7b5a8e0157d7776b987d8963c9c786.js?body=1" data-turbolinks-track="true"></script>
<style>
body {
/*background-color: linen;*/
}
</style>
<script type="text/javascript">
$(document).ready(function() {
$(document).on('click','.show-more',function () {
var $this = $(this);
....
});
});
window.onload = function(){
.....
}
Handlebars.registerHelper('if_even', function(conditional, options) {
....
});
</script>
<!-- Setup our templates -->
</head>
<body>
<div id="load_awesome_comments"></div>
<script type="text/javascript">
$(document).ready(function() {
function hideFurtherComments(){
.....
}
var Comment = Backbone.Model.extend({
....
});
var Comments = Backbone.Collection.extend({
model: Comment,
url: fetch_comments_url,
initialize: function() {
....
},
deferred: Function.constructor.prototype,
fetchSuccess: function(collection, response) {
collection.deferred.resolve();
},
});
var comments = new Comments();
var CommentView = Backbone.View.extend({
el: $("#comments_section"),
render: function() {
....
},
});
var EmptyCommentView = Backbone.View.extend({
el: $("#empty_comments_list"),
render: function() {
....
},
});
var commentView = new CommentView({
collection: comments
});
var emptyCommentView = new EmptyCommentView({
collection: comments
});
comments.deferred.done(function() {
....
});
});
var og_url = $("meta[property='og:url']").attr("content");
$("#original_news_article_link").attr("href", og_url)
</script>
<script src="js/require.js" defer async="true" ></script>
</body>
</html>
Give a look at https://webpack.github.io and http://browserify.org/. Their purpose is to do exactly what you need. You pack all of your Javascript code, Javascript dependencies and CSS in one sole JavaScript file.
The advantage of this method is that users can make use of your module just by including a single JavaScript file; no need to worry about dependencies.
The drawback is that, given that the dependencies are all included in the single file, if in a page you have three modules packed this way that use jQuery, for example, the jQuery code will be downloaded three times.
I am trying to implement a wrapper API file for a ReactJS component.
For example, /js/test.react.js
/** #jsx React.DOM */
var TESTCLASS = React.createClass({
render : function() {
return (
<div> Test </div>
);
}
});
I have written a wrapper JavaScript file for that:
var testClass = {
load: function () {
var script = document.createElement("script");
script.type = "text/jsx";
document.head.appendChild(script);
script.onload = function(){
React.render(
<TESTCLASS/>,
document.body)
};
script.src ="./js/test.react.js";
}
};
Then I can use the wrapper API JavaScript in a third-party HTML.
<html>
<head>
<title>Hello React</title>
<script src="http://fb.me/react-0.12.2.js"></script>
<script src="http://fb.me/JSXTransformer-0.12.2.js"></script>
<script src="http://code.jquery.com/jquery-1.10.0.min.js"></script>
<script type="text/jsx" src="test.js"></script>
</head>
<body>
<div id="content"></div>
<script>
testClass.load();
</script>
</body>
</html>
However, it seems to me /js/test.react.js cannot be dynamically loaded as pure JavaScript file. Can any expert explain to me the reason and provide a proper solution to write my wrapper API JavaScript file?
JSXTransformer*.js exports a global JSXTransformer object which has an exec() function, which transpiles JSX then eval()s the result.
You could try running JSXTransformer.exec() with the script's contents onload first.
Also, FYI, the #jsx pragma is no longer required as of React 0.12 :)
I created a custom element called "memory-box" like the below code.
Please pay attention to the function "logthis" which is in "memory-box-template".
memory-box.html
<template id="memory-box-template">
<input id="memory-box" type="form" />
<input type="button" id="testbutton" />
<script type="text/javascript">
function logthis(me){
console.log(me);
}
</script>
</template>
<script type="text/javascript">
(function() {
var thisDoc = document.currentScript.ownerDocument;
var storage = localStorage;
var proto = Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var temp = thisDoc.querySelector('#memory-box-template');
var con = document.importNode(temp.content, true);
this.createShadowRoot().appendChild(con);
var input = this.querySelector('::shadow #memory-box');
var data = storage.getItem(this.id);
input.value = data;
input.addEventListener('input', saveData.bind(input, this.id));
}
},
});
document.registerElement('memory-box', {
prototype: proto
});
function saveData(id, e) {
storage.setItem(id, this.value);
}
})();
</script>
Now, I uses the custom element "memory-box" like the below code.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="import" href="/html/memory-box.html">
</head>
<body>
<div><memory-box id="memory1"></memory-box></div>
<div><memory-box id="memory2"></memory-box></div>
<div><memory-box id="memory3"></memory-box></div>
<div><memory-box id="memory4"></memory-box></div>
</body>
<script type="text/javascript">
logthis(this);
</script>
</html>
As you can see, I putted a script in the index.html and called the function "logthis" just because I was curious. And no error occurred.
Why?
The function "logthis" is in each shadow doms. It's supposed not able to be called outside the shadow dom, I think.
As explained here, while the HTML within Shadow DOM is encapsulated, any JavaScript is NOT -- it is in the global scope, unless you utilize specific javascript techniques (namescaping, IIFE) to do so.
Hope this helps,
Jonathan Dodd
I just started playing around with backbone.js and am enjoying the quirks of using it.
However am trying to use it for handling events in views for a site am working on.
Am also using namespaces to organise my code
var App = App || {};
App.Views = App.Views || {};
App.Views.Sidebar = Backbone.View.extend({
el: '#app-wrapper',
events : {
"click #rf":"test"
; },
test: function(e) {
alert("testing");
}
})
}
});
Heres the html, its just a skeleton of the site
<html>
<head>
<title>Shopping List</title>
<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="backbone.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript">
App.Views.Sidebar;
</script>
</head>
<body>
<div id="app-wrapper">
<div id="app-header">
<ul>
<li id="rf">Test</li>
</ul>
</div>
</div>
</body>
</html>
However this snippet doesn't seem to work, the test() method is not called when click the #rf element.
Am doing something wrong, am pretty new to this.
You have not instantiated your view. Try something like this:
var myView = new App.Views.Sidebar();
(instead of: App.Views.Sidebar; )
Also don't forget to instantiate your views once the document has been loaded. Something like this (if you use JQuery):
$(function() {
// Initialize Backbone views.
var myView = new App.Views.Sidebar();
});