scope in directive does'nt work - html

I want to add input element to my Google Map.
I wrote the following code:
app.directive('GooglePlaceAutoComplete', function() {
return {
restrict:'AEC',
replace: true,
scope: {
myMap:'='
},
template: '<input id="google_places" name="google_places" type="text" class="input-block-level"></input>',
link: function($scope, elm , attr){
var input = document.getElementById('google_places');
var autocomplete = new google.maps.places.Autocomplete(input);
autocomplete.bindTo('bounds', $scope.myMap);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
alert('changed');
});
}
};
});
When I inspect the element I see that $scope.myMap == Undefined
And therefore get the following error:
TypeError: Cannot read property 'gm_bindings_' of undefined
at kf (https://maps.gstatic.com/maps-api-v3/api/js/21/3/main.js:25:19)
at El.T.(anonymous function).bindTo (https://maps.gstatic.com/maps-api-v3/api/js/21/3/main.js:25:204)
at link (file:///Users/ortal/Desktop/Js%20Excersize%202/googlemapjs.js:28:22)
at file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:72:222
at $ (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:72:278)
at N (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:61:294)
at g (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:54:244)
at N (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:61:239)
at g (file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:54:244)
at file:///Users/ortal/Desktop/Js%20Excersize%202/angular.min.js:53:282
When I remove the following:
scope: {
myMap:'='
},
<div ng-app="app.ui-map" ng-controller="Controller">
<section id="map">
<div id="map_canvas" ui-map="myMap"
style="height:300px;width:400px;border:2px solid #777777;margin:3px; border:1px solid"
ui-options="mapOptions"
ui-event="{'map-idle' : 'onMapIdle()'}"
>
</div>
<div ng-repeat="marker in myMarkers" ui-map-marker="myMarkers[$index]"
ui-event="{'map-click': 'markerClicked(marker)'}"></div>
</section>
<div GooglePlaceAutoComplete></div>
I get no error but the nothing happend when the address is changed

Try adding
scope: true,
To your directive. Like this:
app.directive('GooglePlaceAutoComplete', function() {
return {
restrict:'AEC',
replace: true,
scope: true, <-------- HERE
scope: {
myMap:'='
},
...
...

Related

Vuejs component does not render immediately

I have a vue app and a component. The app simply takes input and changes a name displayed below, and when someone changes the name, the previous name is saved in an array. I have a custom component to display the different list items. However, the component list items do not render immediately. Instead, the component otems render as soon as I type a letter into the input. What gives? Why would this not render the list items immediately?
(function(){
var app = new Vue({
el: '#app',
components: ['name-list-item'],
data: {
input: '',
person: undefined,
previousNames: ['Ian Smith', 'Adam Smith', 'Felicia Jones']
},
computed: {
politePerson: function(){
if(!this.person) {
return 'Input name here';
}
return "Hello! To The Venerable " + this.person +", Esq."
}
},
methods: {
saveInput: function(event){
event.preventDefault();
if(this.person && this.previousNames.indexOf(this.person) === -1) {
this.previousNames.push(this.person);
}
this.setPerson(this.input);
this.clearInput();
},
returnKey: function(key) {
return (key + 1) + ". ";
},
clearInput: function() {
this.input = '';
},
setPerson: function(person) {
this.person = person;
}
}
});
Vue.component('name-list-item', {
props: ['theKey', 'theValue'],
template: '<span>{{theKey}} {{theValue}}</span>'
});
})()
And here is my HTML.
<div id="app">
<div class="panel-one">
<span>Enter your name:</span>
<form v-on:submit="saveInput">
<input v-model="input"/>
<button #click="saveInput">Save</button>
</form>
<h1>{{politePerson}}</h1>
</div>
<div class="panel-two">
<h3>Previous Names</h3>
<div>
<div v-for="person, key in previousNames" #click='setPerson(person)'><name-list-item v-bind:the-key="key" v-bind:the-value="person" /></div>
</div>
</div>
</div>
You are not defining your component until after you have instantiated your Vue, so it doesn't apply the component until the first update.

How to access child scope?

In the below code, I'm trying to get a console log in the Directive (child scope),I need to get scope details.I tried adding a scope variable to the function in the directive also, but didn't work.
How can I fix this?
myDirective.html
<html ng-app="MyAppdr">
<head>
<script src="angular.js"></script>
<script src="appdr.js"></script>
</head>
<body ng-controller="dirCtrl">
<h1>hello</h1>
<employee-card></employee-card>
<!--div employee-card></div>
<div class="employee-card"></div--->
</body>
<html>
employee_info.html
<b>{{employee.name}}</b> - {{employee.job}}
<br/><br/>
<div ng-show='!!employee.followers'>
followers
<ul>
<li ng-repeat='name in employee.followers'>{{name}}</li>
</ul>
<button ng-click="follow('Galaa')">follow</button>
</div>
</div>
appdr.js
name="MyAppdr";
requires=[];
appdr=angular.module(name,requires);
appdr.controller("dirCtrl",function($scope){
console.log("This is controller dirCtrl");
$scope.employee={
name:"subo",
job:"cat",
followers:["chin","adyakshaka","aluu"]
}
console.log("parent ",$scope);
/*
$scope.follow=function(name){
$scope.employee.followers.push(name);
}
*/
});
appdr.directive("employeeCard",function(){
//$scope.employee={};
console.log("child ",$scope);
return{
templateUrl:'employee_info.html',
restrict:"AEC",
//replace:true,
controller:function($scope){
$scope.follow=function(name){
$scope.employee.followers.push(name);
}
},
scope:true
}
});
For your particular case, using scope: false seems to be sufficient if you are not showing multiple cards in same page.
appdr.directive("employeeCard",function() {
return {
scope: false,
// other attributes
If you need to show multiple cards in same page, use isolated scope and pass in
appdr.directive("employeeCard",function() {
return {
scope: {
employee: '='
},
// other attributes
<employee-card employee="employee"></employee-card>
Move the console.log() inside the controller of the directive.
appdr.directive("employeeCard", function() {
return {
templateUrl: 'employee_info.html',
restrict: "AEC",
//replace:true,
controller: function($scope) {
console.log("child ", $scope);
$scope.follow = function(name) {
$scope.employee.followers.push(name);
}
},
scope: true
}
});
If you will have only one employee card on the page then keep scope: true else if you need to show multiple cards in the same page, use an isolated scope and pass it in the template.
appdr.directive("employeeCard", function() {
return {
templateUrl: 'employee_info.html',
restrict: "AEC",
//replace:true,
controller: function($scope) {
console.log("child ", $scope);
$scope.follow = function(name) {
$scope.employee.followers.push(name);
}
},
scope: {
employee: "="
}
}
});
And in the html use something like
<employee-card employee="employee"></employee-card>
Refer the documentation of directive here

How to display a modelpopup window using angularJS?

I need to show a model popup window in a button click.can any one suggest the best method to achieve this in angularjs without BootstrpJS?
I tried the below and is not working. :(
html
<div>
<button ng-click='toggleModal()'>Add Dataset</button>
<modal-dialog info='modalShown' show='modalShown' width='400px' height='60%'>
<p>Modal Content Goes here</p>
</modal-dialog>
</div>
controller
app.controller('DataController', function ($scope,$http) {
$scope.showModal = false;
$scope.toggleModal = function () {
$scope.showModal = !$scope.showModal;
};
$http.get("/api/product").then(function (responses) {
$scope.ProductData = responses.data;
});
.......
........
});
app.directive('modalDialog', function () {
return {
restrict: 'E',
scope: {
show: '=info'
},
replace: true, // Replace with the template below
transclude: true, // we want to insert custom content inside the directive
link: function (scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
scope.hideModal = function () {
scope.show = false;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});
It looks like you're messing with your scope a little too much. If you check out http://codepen.io/dboots/pen/vLeXPj, I used the same $scope.showModal variable and the same the same $scope.toggleModal function to show/hide.
angular.module('testApp', [])
.controller('DataController', function($scope) {
$scope.showModal = false;
$scope.toggleModal = function() {
$scope.showModal = !$scope.showModal;
};
})
.directive('modalDialog', function() {
return {
restrict: 'E',
replace: true, // Replace with the template below
transclude: true, // we want to insert custom content inside the directive
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
},
template: "<div class='ng-modal' ng-show='showModal'><div class='ng-modal-overlay' ng-click='toggleModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='toggleModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});
Make a directive. Then include it in your controller.
See: https://docs.angularjs.org/guide/directive

"[object object]" shown when double-clicking input

Below is the template I am using for the directive. In code we are
fetching the data from a service in that data we have all the
information of that particular person. And from that data we are
showing only first name, last name and designtion or company
affiliation.
<div ng-if="model" class="entry-added">
<span class="form-control"><b>{{model.fullName}}</b>, <br/><span class="small-font">{{(model.designation)?model.designation:model.companyAffiliation}}</span></span>
<a ng-click="removePerson()" class="action-remove"><i class="fa fa-remove"></i></a>
</div>
<div ng-show="!model" class="input-group">
<input type="text"
class="form-control"
name="{{name}}"
id="{{name}}"
placeholder="{{placeholder}}"
ng-required="{{isRequired}}"
typeahead-on-select = "change($item, $model, $label)"
ng-model="model"
typeahead-min-length="3",
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
typeahead-template-url="typeAheadTemplate.html"
typeahead-loading="searching"
typeahead-editable="false">
<script type="text/ng-template" id="typeAheadTemplate.html">
<a class="ui-corner-all dropdown" tabindex="-1">
<div class="col-md-2"><img class="dropdown-image" ng-src="https://people.***.com/Photos?empno={{match.model.employeeNumber}}"></div>
<div>
<div bind-html-unsafe="match.model.fullName"></div>
<div bind-html-unsafe="match.model.designation"></div>
</div>
</a>
</script>
I am using a custom directive to display a search field. The drop down is displaying [object object].
Directive
// In backend taxDeptContact is a Person type object
/*
Directive code
*/
(function () {
'use strict';
angular.module('treasuryApp.directives').directive('employeeSearch', employeeSearch);
employeeSearch.$inject = ['$resource', '$rootScope', 'ErrorHandler'];
function employeeSearch($resource, $rootScope, ErrorHandler) {
return {
restrict: 'E',
require: '^form',
scope: {
model: "=",
isRequired: '#',
submitted: "=",
onSelect: '&',
name: '#',
index:'#'
},
link: function(scope, el, attrs, formCtrl) {
//set required attribute for dynamically changing validations
scope.searchEmployees = function (searchTerm) {
var users = [];
var myResult = [];
var result = $resource($rootScope.REST_URL + "/user/getEmployees", {term: searchTerm}).query().$promise.then(function (value) {
//console.log(value)
$.each(value, function(i, o) {
users.push(o);
});
return users;
});
return result;
}
scope.removePerson = function() {
scope.model=null;
}
scope.userNotSelectedFromTypeahead = function(name) {
if(undefined === formCtrl[name]) {
return false;
}
return formCtrl[name].$error.editable;
};
scope.change = function(item, model, label) {
scope.model = item
scope.onSelect(
{name: scope.name, person: scope.model});
},
templateUrl: 'app/components/common/directives/employee-search.tpl.html'
};
}
})();
View that is using the directive
<div class="form-group">
<label class="col-sm-3>Tax Dept Contact</label>
<div class="col-sm-4">
<employee-search model="reqCtrl.requestObj.taxDepartmentContact" name="taxDeptContact" is-required="false" submitted="reqCtrl.submitted"/>
</div>
</div>
Image of the error occuring
Looks like this may be your trouble spot
typeahead="suggestion for suggestion in searchEmployees($viewValue)"
suggestion for suggestion is pulling the whole object. Have you tried displaying a particular attribute of suggestion?
For example: if you had a suggestion.name attribute you would write:
typeahead="suggestion.name for suggestion in searchEmployees($viewValue)"
Finally got the answer: I used autocomplete="off" in my directive and thats all
<input type="text" autocomplete="off" />

How to access polymer when "this" becomes "that"

I am trying to integrate dropzone.js and cloudinary into Polymer 1.0. It does work, but I am hitting a stumbling block on how to send the dynamic URL generated by Cloudinary back to Polymer so I can write that URL into Firebase. I am inside a function listening to dropzone events with the intention of using iron-signals to signal a different web component. "this" is now scoped to dropzone.js and not Polymer.
..resulting in "Uncaught TypeError: this.fire is not a function".
The code is below, I am trying to start the iron-signal based on listening the dropzone.js "success" event which provides access to the new image URL.
<link rel="stylesheet" href="../../../bower_components/dropzone/dist/min/dropzone.min.css">
<dom-module id="my-dropzone">
<style>
:host {
display: block;
}
div#my-dropzone-area {
max-width=300px;
height=300px;
border: 4px dashed blue;
}
</style>
<template>
<paper-button on-tap="startTheMessage">Test Fire!</paper-button>
<iron-signals on-iron-signal-hello="passTheMessage">
<div class="dropzone" id="my-dropzone-area">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</div>
</template>
</dom-module>
<script>
(function() {
Polymer({
is: 'my-dropzone',
ready: function() {
// access a local DOM element by ID using this.$
Dropzone.options.myDropzoneArea = {
paramName: 'file', // The name that will be used to transfer the file
maxFilesize: 10, // MB
uploadMultiple: false,
acceptedFiles: '.jpg,.png,.jpeg,.gif',
parallelUploads: 6,
addRemoveLinks: true,
url: 'https://api.cloudinary.com/v1_1/remarkable-ky/image/upload',
init: function() {
this.on('addedfile', function(file) {
console.log('Added file.');
console.log(file);
});
this.on('sending', function(file, xhr, formData) {
console.log('Sending file.');
formData.append('api_key', 0000000000000);
formData.append('timestamp', Date.now() / 1000);
formData.append('upload_preset', 'where-ky');
});
this.on('success', function(file, response) {
var baseURL = 'http://res.cloudinary.com/remarkable-ky/image/upload/';
var url = baseURL.concat(response.public_id);
console.log('Cloudinary URL: ', url);
this.fire('iron-signal', {
name: 'hello',
data: null
});
});
}
};
},
startTheMessage: function() {
this.fire('iron-signal', {
name: 'hello',
data: null
});
},
passTheMessage: function() {
alert("got it");
},
properties: {},
});
})();
</script>
<script src="../../../bower_components/dropzone/dist/min/dropzone.min.js"></script>
you can pass this into the function with the .bind() function.
this.on('success', function(file, response) {
var baseURL = 'http://res.cloudinary.com/remarkable-ky/image/upload/';
var url = baseURL.concat(response.public_id);
console.log('Cloudinary URL: ', url);
this.fire('iron-signal', {
name: 'hello',
data: null
});
}.bind(this));