AngularJS Custom directives Not Showing - javascript

Learning AngularJS and I can't seem to see what's wrong with my custom directives. Using a modified w3 school code to show a simpler example of my problem.
When I lunch the demo.html in google chrome I only get a white screen.
Top snip - demo.html
Bottom snip - app.js
(function(){
var app = angular.module("myApp", []);
var direc = function()
{
return
{
restrict : 'A',
template : "<h1>Made by a directive!</h1>"
};
};
app.directive("w3TestDirective", direc);
})();
<!DOCTYPE html>
<html>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="app.js" type="text/javascript"></script>
<body ng-app="myApp">
<div w3-test-directive></div>
</body>
</html>

Syntax error: You do not need a closing parantheses while defininig direc function.
(function(){
var app = angular.module("myApp", []);
var direc = function()
{
return
{
restrict : 'A',
template : "<h1>Made by a directive!</h1>"
}
};// You had extra closing parantheses here
app.directive("w3TestDirective", direc);
})();

Related

Forcing AngularJS directive to link outside digest cycle

This refers to an Angular 1 application.
If the DOM is modified outside the context of my angular application, I know I can use angular.element(document.body).scope().$apply() to force the whole app to re-render, including the newly injected content.
However my directives never seem to link.
So in the example below, the markup <message></message> should render Hello World, but when it is injected manually, then digest applied, the link method never appears to run.
https://jsbin.com/wecevogubu/edit?html,js,console,output
javascript
var app = angular.module('app', [])
app.directive('message', function() {
return {
template: 'Hello, World!',
link: function() {
console.log('message link')
}
}
})
document.getElementById('button').addEventListener('click', function() {
document.getElementById('content').innerHTML = '<message>default content</message>'
var scope = window.angular.element(document.body).scope()
scope.$apply()
})
html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.0/angular.min.js"></script>
</head>
<body ng-app="app">
inside app:
<message></message>
outside app:
<button id="button">Print another message</button>
<div id="content"></div>
</body>
</html>
According to the docs, you can do this with angular.injector
angular.injector allows you to inject and compile some markup after the application has been bootstrapped
So the code for your example could be:
document.getElementById('button').addEventListener('click', function() {
var $directive = $('<message>default message</message>');
$('#content').append($directive);
angular.element(document.body).injector().invoke(function($compile) {
var scope = angular.element($directive).scope();
$compile($directive)(scope);
});
})
Hope this is what you are looking for!

Defining Polymer element after importing ES6 code via System.js

I'm creating an HTML element using Polymer, and I want it to be able to work with an ES6 class I've written. Therefore, I need to import the class first and then register the element, which is what I do:
(function() {
System.import('/js/FoobarModel.js').then(function(m) {
window.FoobarModel = m.default;
window.FoobarItem = Polymer({
is: 'foobar-item',
properties: {
model: Object // instanceof FoobarModel === true
},
// ... methods using model and FoobarModel
});
});
})();
And it works well. But now I want to write a test HTML page to display my component with some dummy data:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="/bower_components/webcomponentsjs/webcomponents.js"></script>
<script src="/bower_components/system.js/dist/system.js"></script>
<script>
System.config({
map:{
traceur: '/bower_components/traceur/traceur.min.js'
}
});
</script>
<link rel="import" href="/html/foobar-item.html">
</head>
<body>
<script>
(function() {
var data = window.data = [
{
city: {
name: 'Foobar City'
},
date: new Date('2012-02-25')
}
];
var view;
for (var i = 0; i < data.length; i++) {
view = new FoobarItem();
view.model = data[i];
document.body.appendChild(view);
}
})();
</script>
</body>
</html>
Which isn't working for one simple reason: the code in the <script> tag is executed before Polymer registers the element.
Thus I'd like to know if there's a way to load the ES6 module synchronously using System.js or even better, if it's possible to listen to a JavaScript event for the element registration (something like PolymerElementsRegistered)?
I've tried the following without success:
window.addEventListener('HTMLImportsLoaded', ...)
window.addEventListener('WebComponentsReady', ...)
HTMLImports.whenReady(...)
In the app/scripts/app.js script from the polymer starter kit, they use auto-binding template and dom-change event
// Grab a reference to our auto-binding template
var app = document.querySelector('#app');
// Listen for template bound event to know when bindings
// have resolved and content has been stamped to the page
app.addEventListener('dom-change', function() {
console.log('Our app is ready to rock!');
});
Also check this thread gives alternatives to the polymer-ready event.

Ng-if - Try to get data of my Firebase

I have a number in my Firebase and I want to get it in my ng-if.
I've try a Snapshot, my console log display good value but it's seems to be ignore by ng-if.
Maybe I've miss something ...
My Ng-If :
<div class="item" ng-if="distanceTo(event) < dist ">
My JS :
userRef.child($scope.currentUser.authResponse.userID)
.child("settings")
.child("distance")
.once('value', function(snap) {
console.log(snap.val())
$scope.dist = snap.val()
console.log($scope.dist)
})
$scope.distanceTo = function(event) {
var distance = GreatCircle.distance(event.addressid.geometry.location.H,
position.longitude,
position.latitude,
event.addressid.geometry.location.L )
event.distance = distance
distance = distance.toFixed(1)
return distance
};
<div class="item" ng-if="distanceTo(event) < dist ">
The issue is that the Angular is unaware of when your Firebase listener gets updated. You have two options: use $timeout (not recommend), or use AngularFire (highly, highly recommend).
With $timeout you would do something like this:
.controller('MyCtrl', function($scope, $timeout) {
var ref = new Firebase('<my-firebase-app>');
// get the user
$scope.currentUser = ref.getUser();
var userRef = ref.child($scope.currentUser.uid).child("settings/distance");
userRef.on('value', function(snap) {
$timeout(function() {
$scope.dist = snap.val();
});
});
});
With AngularFire, this is much, much easier:
angular.module('app', ['firebase']) // include AngularFire
.controller('MyCtrl', function($scope, $firebaseObject) {
var ref = new Firebase('<my-firebase-app>');
$scope.dist = $firebaseObject(ref);
});
Check out the AngularFire quickstart to get up and running and save yourself a lot of time and agony :)
Assuming that your distanceTo function is working ok (I was not able to test that so I mocked it), the problem lies in the fact that $scope.dist is not getting set.
Check which of your console.logs are happening. I suspect they are not happening. Therefore, the problem lies in the line
userRef.child($scope.currentUser.authResponse.userID).child("settings").child("distance").once('value',
Also I noticed you don't use semi-colons. That's not a good practice and for all I know might be contributing to the problem.
var myApp = angular.module('myApp', []);
myApp.controller('myController', ['$scope',
function($scope) {
$scope.distanceTo = function(event) {
return 10;
var distance = GreatCircle.distance(event.addressid.geometry.location.H, position.longitude, position.latitude, event.addressid.geometry.location.L);
event.distance = distance;
distance = distance.toFixed(1);
return distance;
};
/* userRef.child($scope.currentUser.authResponse.userID).child("settings").child("distance").once('value', function(snap) {
console.log(snap.val())
$scope.dist = snap.val()
console.log($scope.dist)
});
*/
}
]);
.item {
height: 50px;
width: 50px;
background-color: green;
}
input {
width: 300px;
}
<html ng-app="myApp" ng-controller="myController" ng-init="dist = 10">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body>
<input type=text ng-model="dist" placeholder="values > 10 will make the item show" />
<div class="item" ng-if="distanceTo(event) < dist ">
</body>
</html>

Component gets error this.getView is not a function

I'm going over the sapui5 walkthrough tutorials and have managed to get to step 9 where it teaches you how to use Component.js file in your app.
Now, prior to using Component.js everything in the app was working fine. However, once I try to use component I get this error:
Uncaught TypeError: this.getView is not a function
Referring to UIComponent.js line 6. Even though my component file is just called Component.js. I also get:
GET http://localhost:58736/InvoicesApp/invoicesapp/Component-preload.js 404 (Not Found)
But I'm not sure they're related
Here is my index.html
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
<script src="resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.m"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-bindingSyntax="complex"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"
>
</script>
<!-- only load the mobile lib "sap.m" and the "sap_bluecrystal" theme -->
<script>
sap.ui.localResources("invoicesapp");
sap.ui.getCore().attachInit(function () {
new sap.ui.core.ComponentContainer({
name : "invoicesapp"
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody" id="content"/>
</html>
My Component.js
sap.ui.define([
"sap/ui/core/UIComponent",
"sap/ui/model/json/JSONModel",
"sap/ui/model/resource/ResourceModel"
], function (UIComponent, JSONModel, ResourceModel) {
"use strict";
return UIComponent.extend("invoicesapp.Component", {
metadata: {
rootView:"invoicesapp.view.App"
},
init : function () {
// call the init function of the parent
UIComponent.prototype.init.apply(this, arguments);
// set data model on view
var oData = {
recipient : {
name : "World"
}
};
var oModel = new JSONModel(oData);
this.getView().setModel(oModel);
// set i18n model on view
var i18nModel = new ResourceModel({
bundleName: "invoicesapp.i18n.i18n"
});
this.getView().setModel(i18nModel, "i18n");
}
});
});
My controller
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast",
"sap/ui/model/json/JSONModel",
"sap/ui/model/resource/ResourceModel"
], function (Controller, MessageToast, JSONModel, ResourceModel) {
"use strict";
return Controller.extend("invoicesapp.controller.App", {
onShowHello : function () {
// read msg from i18n model
var oBundle = this.getView().getModel("i18n").getResourceBundle();
var sRecipient = this.getView().getModel().getProperty("/recipient/name");
var sMsg = oBundle.getText("helloMsg", [sRecipient]);
// show message
MessageToast.show(sMsg);
}
});
});
In the component you can't call this.getView() because there is no getView(), the api docs at https://openui5beta.hana.ondemand.com/#docs/api/symbols/sap.ui.core.Component.html
Instead, you set the model directly on the component itself. In other words, just call
this.setModel(oModel);
and
this.setModel(i18nModel, "i18n");
By the way: in the walktrough it's done the same way.
this.getView() will not be defined in component.js as view is yet to be instantiated.
You can simply set model with just this.setModel(oModel) and you can set names model by this.setModel(oModel,"modelName");
I also had the same problem while going through the walk through.
View is not instantiated in the Component.
You can rewrite as
this.setModel("myModel);
And for i18n
this.setModel(i18nModel,"i18n");
This error was there in walk through but now its fixed it seems. There were few errors with the SAP UI5 Tutorials while I was learning but they have fixed most of them now.
This is also a good source to start with UI5. Almost similar to Demokit.
UI Development Toolkit for HTML5 (SAPUI5)
Happy Coding
Febin Dominic

React error "Uncaught TypeError: type.toUpperCase is not a function" on a hello world app

I have started dabbling with reactjs, and on following a tutorial and I got the error on the title, just on running a very simple hello world app. Below is the single page code I have:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://fb.me/react-0.13.3.js"></script>
<script src="https://fb.me/JSXTransformer-0.13.3.js"></script>
</head>
<body>
<script type="text/jsx">
// Define a class
var HelloWorld = React.createClass({
render: function() {
return <div>
Hello World!
</div>
}
});
// create element with this class
var element = React.createElement({HelloWorld});
// Render this class and place it in the body tag
React.render(element, document.body);
</script>
</body>
</html>
Any hints or resolution are very much appreciated.
In my case I have created a React element, but I forgot to export it on the end of the file:
var React = require('react');
var About = React.createClass({
render: function(){
return (
<div>
<h1>The about page</h1>
</div>
);
}
});
export {
About, About as default
};
There is a mistake in the following line:
var element = React.createElement({HelloWorld});
It should be:
var element = React.createElement(HelloWorld);
Notice the lack of the curly braces.
Hey the proper way to render the element is
React.render(<HelloWorld />, document.body);
You don't need to create the element first. So overall your code should look like
var HelloWorld = React.createClass({
render: function () {
return <div > Hello World! < /div>
}
});
React.render( < HelloWorld / > , document.body);

Categories

Resources