How can i move the javascript code that's using knockout outside the html file? I want to create a separate file where everything is handled (or as much as possible). Also the templating should still work. Thanks in advance!
EDIT: Changes made. I have added the require.js in my Scripts folder and made an app.js and viewmodel.js file. But this still won't work. Any help would be very much appreciated :)
EDIT2: Almost there, Rumesh Eranga gave the right answer with using require.js. I only have a little problem left with my binding. 'data-bind="text: $(item.name)"' won't show the name, only '[object Object]'.
EDIT3: SOLVED!
This is the HTML file:
<head>
<script type="text/javascript" data-main="Script/app.js" src="Scripts/require.js"></script>
</head>
<body>
<script src="http://code.jquery.com/jquery-1.7.1.min.js"></script>
<script src="Scripts/jquery.tmpl.js"></script>
<script id="shoppingItemTemplate" type="text/html">
<li><span data-bind="text: item.name"></span></li>
</script>
<div id="ActiveShoppingList">
<h2>Shopping items</h2>
<div id="ActiveList">
<ul data-bind="template: {name:'shoppingItemTemplate', foreach: items, as:'item'}"></ul>
<button data-bind="click:addItem">Add item</button>
</div>
</div>
</body>
Here is my Script/app.js:
require(['knockout-3.2.0', 'viewmodel'], function(ko, viewmodel) {
ko.applyBindings(new viewmodel);
});
And here is my Script/viewmodel.js:
define(['knockout-3.2.0'], function(ko) {
return function viewmodel (){
this.items = ko.observableArray([new item("item1"), new item("item2")]);
this.addItem = function()
{
this.items.push(new item("new item"));
};
};
function item(name)
{
return { name: ko.observable(name) };
}
});
Use Asynchronous Module Definition (AMD) With RequireJs.
Good article on Require and knockout can be found here.
Quoting from the site.
HTML
<html>
<head>
<script type="text/javascript" data-main="scripts/init.js" src="scripts/require.js"></script>
</head>
<body>
<p>First name: <input data-bind="value: firstName" /></p>
<p>First name capitalized: <strong data-bind="text: firstNameCaps"></strong></p>
</body>
</html>
scope/init.js
require(['knockout-x.y.z', 'appViewModel', 'domReady!'], function(ko, appViewModel) {
ko.applyBindings(new appViewModel());
});
scripts/appViewModel.js
// Main viewmodel class
define(['knockout-x.y.z'], function(ko) {
return function appViewModel() {
this.firstName = ko.observable('Bert');
this.firstNameCaps = ko.pureComputed(function() {
return this.firstName().toUpperCase();
}, this);
};
});
According to the code snippet given above you can see that you can make your view model code separate from the html and even can be modularize which is much helpful.
Related
I need to run this code in angularjs.
When I try to execute this model function it is not running.
It is not even showing alert or console.
So what is the way to use this script files in angularjs
Here is my code in example.html:
<div>
{{sample}}
</div>
<div><button ng-click="name()"></div>
<script>
function name(){
alert("text");
}
</script>
If i understand your requirement correctly,
You need to execute a separate java-script function.
For an angular application it is not a proper way to run javascript out of scope of angular.
any if it is absolutely requried you can try replacing ng-click="name()" with onclick="name()"
var app = angular.module("app", []);
app.controller('exampleController', [function() {
this.myFunction = function() {
alert("Iam from angular controller");
}
}]);
function myFunction() {
alert("Iam from javascript");
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="app" ng-controller="exampleController as ctrl">
<button ng-click="ctrl.myFunction()">click me</button>
<button onclick="myFunction()">click me</button>
</div>
#Update
If you want to use a java script library or function or constants in angularjs the my suggested way is to add a factory or service that ensure the library or function or constants but it is not simple as above solution.Here iam adding a snippet based on above solution
There are some advantages of using following approch :-
It will add dependency injection proprely which is a basic concept behind angularjs
It will ensure that the external function exist before starting app.
It will add more flexibility and control over the java script function in angular.
The below snippet will remove the external access of function and secure your application
This is the best way in which you can add external libraries like jquery loadash or any js libraries to your code
(function() {
function exampleController(myFunction) {
this.myFunction = function() {
alert("Iam from angular controller");
}
this.externalJSFunction = myFunction
};
exampleController.$inject = ['myFunction'];
function myFunctionFactory($window) {
if (!$window.myFunction) {
throw new Error("myFunction is not defined");
}
this.myFunction = $window.myFunction;
/* You can add
$window.myFunction = undefined;
if the function ($window.myFunction) is not required by
some other library or function in window scope
in such cases it gives added security by
restricting access of this from window scope and dis allows modification
*/
return this.myFunction;
}
myFunctionFactory.$inject = ['$window'];
var app = angular.module("app", []);
app.controller('exampleController', exampleController);
app.factory('myFunction', myFunctionFactory);
})();
function myFunction() {
alert("Iam from javascript");
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
<div ng-app="app" ng-controller="exampleController as ctrl">
<button ng-click="ctrl.myFunction()">click me For angular Function</button>
<br/>
<button ng-click="ctrl.externalJSFunction()">click me For external JS Function </button>
<br/>
<button onclick="myFunction()">click me for checking exteranl acess </button>
</div>
your code should be like this....
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.12/angular.js" data-semver="1.4.9"></script>
<script >
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name=function(){
alert("text");
}
});
</script>
</head>
<body ng-controller="MainCtrl">
<div>
{{sample}}
</div>
<div><button ng-click="name()">click me</div>
</body>
</html>
You need to give angular js cdn first and then a create a module and controller like above
Here is a sample controller.
<body ng-app="myApp" ng-controller="myCtrl">
<div>
<button ng-click="name()">
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = name;
function name(){
alert("text");
}
});
</script>
</body>
You could use a directive, here is an example:
// in your JS source
angular.directive('something', [function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('click', function() {
alert('yup');
});
}
};
}]);
// in your HTML file
<button type="button" something>Click Me!</button>
This allows you to reuse your various code chunks / functions across your entire project pretty easily.
Another Solution
<!DOCTYPE html>
<html>
<head>
<title>example</title>
<script data-require="jquery#*" data-semver="3.1.1" src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="exampleController as ctrl">
<button ng-click="ctrl.name()">click me to angular</button>
<button ng-click="name()" class="btn">click me to javascript</button>
<script>
var app = angular.module("app", []);
app.controller('exampleController', [function() {
this.name = function() {
alert("angular text");
}
}]);
//JQuery Lib must be included your project
$(document).on('click', '.btn', function() {
eval($(this).attr('ng-click'));
});
function name() {
alert("javascript text");
}
</script>
</body>
</html>
You should be able to run any javascript inside of an angular controller inside of a script tag in an html file.
Your html file should look something more like this:
<!DOCTYPE html>
<html>
<head>
<title>example</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
</head>
<body ng-app="app" ng-controller="exampleController as ctrl">
<button ng-click="ctrl.name()">click me</button>
</body>
</html>
<script>
var app = angular.module("app", []);
app.controller('exampleController', [function() {
this.name = function(){
alert("text");
}
}]);
</script>
Create a service layer and glue it inside the controller. Now, you can reuse the created function in multiple controllers.
For implementation,
How can I call javascript function in AngularJS controller?
I hope this helps!
I have just started working on Angularjs and facing a problem in calling the factory defined in other module. Actually I need to clean the code so I have to build all the functionalities in one js file and I have to use them in my main js file where I have defined my controllers. I have made a simple code to understand the problem. Thanks in advance
Following is the Html file:-
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="function.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="MyServiceModuleOne">
<div ng-controller="TestController">
<button type="button" ng-click="getFn()"> Test </button>
</div>
</body>
</html>
Following is script.js file
var myModule= angular.module('MyServiceModuleTwo',['MyServiceModuleOne']);
myModule.controller('TestController', ['$scope', 'notify', function($scope, notify){
$scope.getFn = function() {
notify.sampleFun();
}
}]);
Following is function.js file:-
var myModule = angular.module('MyServiceModuleOne', []);
myModule.factory('notify', function() {
return {
sampleFun: function() {
alert('hi');
}
};
});
There are couple of changes needed.
You are referencing MyServiceModuleOne as root module, but the controller you are referencing is in MyServiceModuleTwo.
So change your ng-app from MyServiceModuleOne to MyServiceModuleTwo.
I've updated the plnkr
I have the following code:
app.controller('MatrixExpertCtrl', function($scope,$http){
$scope.PassedMatrix=[];
$scope.GetMatrixFromServer=function(){
$http.get("http://localhost:3000/getmatrixfromdb").success(function(resp){
alert("The matrix grabbed from the server is: " + resp[0].ans);
$scope.PassedMatrix.push(resp[0].ans);
});
};
$scope.DispSize=function(){
alert("testing");
alert("The size is "+$scope.PassedMatrix[0].size) ;
};
//$scope.GetMatrixFromServer();
});
Now, suppose, in HTML, I have something like this:
<div class="col-sm-3 col-md-3 col-lg-3">
<div class="text-center">
<h3>Example Survey</h3>
<p>example paragrah</p>
<p>More random text</p>
<p>ending the paragraphs</p>
<button id="updmat" ng-click="DispSize();" type="button" class="btn btn-default">Updates</button>
</div>
//Much more code
<div id="body2">
<div class="col-sm-6 col-md-6 col-lg-6" style="background-color:#ecf0f1;">
<div ng-controller="MatrixExpertCtrl" ng-app="app" data-ng-init="GetMatrixFromServer()">
<div class="text-center">
Meaning with this:
Is it possible to call a function that is defined inside a controller, from outside of the scope of that same controller?
I need this because the function is manipulating a shared object, owned by the controller in a very very simple fashion (for example, clicking on the button changes the color of a given element).
I am having trouble to make this work, any help will be appreciated.
I think that declaring some data structures as global would help me solving this problem, but, I would like to avoid doing that because, besides it being bad practice, it might bring me more problems in the future.
If i understand your problem correctly than what you basically do have is one utility function which will work on your shared object and do your useful things (i.e. clicking on the button changes the color of a given element) and now you do require the same behaviour in another controller outside of it's scope. You can achieve the same thing in 2 different ways :
1).Create a service and make it available in your controllers like this :
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.factory('myService', function() {
return {
changeColour: function() {
alert("Changing the colour to green!");
}
};
});
myApp.controller('MainCtrl', ['$scope', 'myService', function($scope,
myService) {
$scope.callChangeColour = function() {
myService.changeColour();
}
}]);
</script>
</head>
<body ng-controller="MainCtrl">
<button ng-click="callChangeColour()">Call ChangeColour</button>
</body>
</html>
Pros&Cons: More angularistic way, but overhead to add dependency in every different controllers and adding methods accordingly.
2).Access it via rootscope
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.run(function($rootScope) {
$rootScope.globalChangeColour = function() {
alert("Changing the colour to green!");
};
});
myApp.controller('MainCtrl', ['$scope', function($scope){
}]);
</script>
</head>
<body ng-controller="MainCtrl">
<button ng-click="globalChangeColour()">Call global changing colour</button>
</body>
</html>
Pros&Cons: In this way, all of your templates can call your method without having to pass it to the template from the controller. polluting Root scope if there are lots of such methods.
try removing semicolon
ng-click="DispSize()"
because it binds ng-click directive to the function.
Trying to get a simple example with firebase and knockoutjs working. All i'm trying to do is take what is in firebase and bind it to my template in knockout. Sounds simple enough right? Well here is the code that's not working. I've looked it over but maybe I'm missing something. Oh this also makes use of knockoutfire.
<!DOCTYPE html>
<html>
<head>
<title>knockout</title>
</head>
<body>
<div id="viewModel">
<ul data-bind="foreach: chat">
<li data-bind="text: nick"></li>
</ul>
</div>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="https://getfirebug.com/firebug-lite.js"></script>
<script type="text/javascript" src="knockout.js"></script>
<script type='text/javascript' src='https://cdn.firebase.com/v0/firebase.js'></script>
<script type="text/javascript" src='knockoutFire/knockoutFire.js'></script>
<script type="text/javascript" src='model.js'></script>
</body>
</html>
and the model.js:
var firebase = new Firebase("https://kingpinapp.firebaseio.com");
var viewModel = KnockoutFire.observable(firebase, {
chat: {
nick: true,
}
});
ko.applyBindings(viewModel, document.getElementById("viewModel"));
if I'm some how getting the model view wrong checkout the firebaseio link to see how the data is laid out. All I get when I visit index.html is a list with nothing in it. Just a bullet point, nothing else.
EDIT: just realised no one else can see my data. Well here is the JSON downloaded from the url:
{
"chat" : {
"nick" : "hello"
}
}
I think you must use with: chat instead of foreach: chat
<ul data-bind="with: chat">
If you need foreach binding, data in firebase look like;
{
"chat": {
"-XXX": {"nick": "hello"},
"-YYY": {"nick": "hi"}
}
}
and code:
var viewModel = KnockoutFire.observable(firebase, {
chat: {
"$chat": {
nick: true,
}
}
});
Am newbie in KnockoutJs, i tried all tutorials on its official website.
Now i want to run all the practical tutorial on my local machine, i have downloaded knockout-2.1.0.js.
I tried this code but its not working on local machine
index.php
---------
<!DOCTYPE html>
<html>
<head>
<title>Knockout</title>
<script src="js/knockout-2.1.0.js"></script>
<link rel="stylesheet" href="css/styles.css" />
<script>
// This is a simple *viewmodel* - JavaScript that defines the data and behavior of your UI
function AppViewModel() {
this.myname= ko.observable("Frank");
this.myage= ko.observable("26");
this.mydetails= ko.computed(function() {
var x;
return this.myname() + ", and my age is " + this.myage() + 'yr. old.';
}, this);
this.capitalizeMyName = function() {
var currentVal = this.myname(); // Read the current value
this.myname(currentVal.toUpperCase()); // Write back a modified value
};
}
// Activates knockout.js
ko.applyBindings(new AppViewModel());
</script>
</head>
<body>
<p>New Application</p>
<!-- This is a *view* - HTML markup that defines the appearance of your UI -->
<p>My Name: <strong data-bind="text: myname"></strong></p>
<p>My Age: <strong data-bind="text: myage"></strong></p>
<p>My Name: <input data-bind="value: myname" /></p>
<p>My Age: <input data-bind="value: myage" /></p>
<p>Full Detalis: <strong>Hi, my name is <text data-bind="text: mydetails"></strong></p>
<button data-bind="click: capitalizeMyName">Go caps</button>
</body>
</html>
If Someone has knowledge or idea about this, then suggest me. Thanks!
http://code.jquery.com/jquery-1.7.2.min.js
you need to include Minified file : js/jquery-1.7.2.min.js
And put your viewmodel code between:
$(document).ready(function(){
// This is a simple *viewmodel* - JavaScript that defines the data and behavior of
});