Cannot get value from getPlace after place-auto-complete using coffeescript - javascript

I am a newbie on angularJs/coffeescript and is trying to integrate it with google maps.
Objective, is to get the place_id after auto-complete using getPlace() and store it somewhere safe by passing it on to a service method so that it can be saved used later.
Here is the code
coffeecode
class SomeController
constructor: (#$scope, #$log, #$location, #SomeService) ->
#listing = {}
getPlace: (place) ->
place = #getPlace()
alert(place.place_id)
return place
doSomethingMore: () ->
#variable.whereGeo = #getPlace().place_id
alert(#listing.whereGeo)
#SomeService.someFunction(#listing) //save the place id somewhere
controllersModule.controller('SomeController', SomeController)
HTML
<div ng-controller="SomeController as sc">
<div class="col-sm-3">
<input places-auto-complete type="text" class="form-control" name="where" id="where" placeholder=""
ng-model="sc.search.where" on-place-changed="sc.getPlace(place)">
</div>
<div ng-show= "sc.place.length">
<p>Ideally something should Appear here after autocomplete </p>
place_id = {{ sc.place }} <br/>
</div>
<div class="col-sm-offset-4 col-sm-2 col-xs-1 text-right">
<button ng-click="sc.doSomethingMore()" class="btn btn-success btn-lg" id="btn_create">Submit</button>
</div>
</div>
Now the module used is ngMap. Here is the links
angular-google-maps
Now let me add the details and the problem.
The autocomplete works fine
The getPlace function gets called
The alert is thrown with the place_id as expected. But , i dont
get the data back in sc.place
On pressing submit , I get the error this.getPlace is
undefined.
Things I have tried. I have used the fat arrow => in getPlace and got this.getPlace is undefined error and no alert is thrown on calling the getPlace either.
Tried looking up here and here and did the solution but didn't get it to work.
Also this was useful to understand the scenario but didn't help
Any help regarding this is highly appreciated. Thanks in advance.

Ok.. So I was doing it wrong. After some research found this. I had got the scope all wrong. Explanation at the end.
Coffeescript
class SomeController
constructor: (#$scope, #$log, #$location, #SomeService) ->
#listing = {}
#place
autocomplete_options = {
types: ['geocode']
}
autocomplete = new google.maps.places.Autocomplete(document.getElementById('where'), autocomplete_options)
google.maps.event.addListener autocomplete, 'place_changed', =>
place = autocomplete.getPlace()
console.log(place.place_id)
#$scope.$apply =>
#$scope.place = place.place_id
doSomethingMore: () ->
#liating.whereGeo = #$scope.place // now place id is available in scope
alert(#listing.whereGeo)
#SomeService.someFunction(#listing) //save the place id somewhere
controllersModule.controller('SomeController', SomeController)
HTML
<div ng-controller="SomeController as sc">
<div class="col-sm-3">
<input type="text" class="form-control" name="where" id="where" placeholder=""
ng-model="sc.search.where">
</div>
<div class="col-sm-offset-4 col-sm-2 col-xs-1 text-right">
<button ng-click="sc.doSomethingMore()" class="btn btn-success btn-lg" id="btn_create">Submit</button>
</div>
</div>
Explanation
For what had to be achieved , the place_id had to be assigned to a
global variable and then made available throughout scope.
The difference between => and -> in coffescript has to be kept in mind. I found some good documentation here
Finally this answer was helpful

Related

How to update the input box date through ngModel in ngb-Datepicker?

I have an input box which uses ngb-datepicker for the date. When I am trying to get the value from date picker through ngModel, it is working. But it is not working when I am trying to update ngModel from the function, input box is not getting updated. Please find the snippet below just for reference.
working stackblitz link is - Working Link
Selecting the date from calendar first and then the next day is updating the value in modal but not in the input box.
<!-- typescript code -->
import {Component} from '#angular/core';
#Component({
selector: 'ngbd-datepicker-popup',
templateUrl: './datepicker-popup.html'
})
export class NgbdDatepickerPopup {
model ;
nextDay() {
this.model.day = this.model.day +1 ;
}
}
<!-- Html code -->
<form class="form-inline">
<div class="form-group">
<div class="input-group">
<input class="form-control" placeholder="yyyy-mm-dd"
name="dp" [(ngModel)]="model" ngbDatepicker #d="ngbDatepicker">
<div class="input-group-append">
<button class="btn btn-outline-secondary calendar" (click)="d.toggle()" type="button"></button>
</div>
</div>
</div>
</form>
<hr/>
<button class="btn btn-sm btn-outline-primary mr-2" (click)="nextDay()">Next Day</button>
<pre>Model: {{ model | json }}</pre>
As I said in the comment, there is some point in the component tree where has been set ChangeDetectionStrategy.OnPush. In this case, inside the ngb-datepicker source code, you can see that this strategy is used.
This means that the change detection algorithm will be executed in its lighter version, and it will trigger an update only if the variable reference is changed.
So, in order to trigger change detection, you have to assign a new object to the variable rather than changing the property in place.
You can take advantage of the spread operator to have a more elegant code:
this.model = {...this.model, day: this.model.day+1};
Or just create a new object in the old style way:
this.model = Object.assign({}, this.model, {day: this.model.day+1});

Modal window comment editing module (editable text)

I want to make, that during the ediditing comment action, I have modal window with comment text written inside textarea, and it is editable without deleting all text with clicking. I tried just to put value inside textarea or placing it in placeholder. But both options are wrong and doesnt work.
Can someone take a look on this code and give me an advice, how should I take for it.
editComment.html
<div class="modal-header">
<h3 class="modal-title" id="modal-title">Edytuj komentarz</h3>
</div>
<div class="modal-body" id="modal-body">
<div class="row">
<div class="col-sm-12">
<div class="row">
<div class="col-sm-12 form-group">
<label>Treść</label>
<textarea class="form-control input-sm"
name="description"
ng-maxlength="512"
ng-model="$ctrl.selected"
rows="6">{{comment.value()}}</textarea>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-raised btn-primary"
type="button"
ng-disabled="!$ctrl.selected"
ng-click="$ctrl.ok()">Zapisz
</button>
<button class="btn btn-raised btn-warning"
type="button"
ng-click="$ctrl.cancel()">Anuluj
</button>
</div>
editComment.js
(function() {
'use strict';
angular.module('settlerApplication').controller('EditCommentCtrl', function($uibModalInstance) {
var $ctrl = this;
$ctrl.ok = function() {
$uibModalInstance.close($ctrl.selected);
};
$ctrl.cancel = function() {
$uibModalInstance.dismiss('cancel');
};
});
})();
I'm not sure to understand what you are trying to achieve. But anyway : if you want to init your textarea's ng-model with $ctrl.foo (comment.value() in your case, from what I understood), you should either :
In the controller, init your $ctrl.selected variable with this value :
$ctrl.selected = $ctrl.foo;
Or, in your template, use ng-init :
<textarea class="form-control input-sm"
ng-init="$ctrl.selected = $ctrl.foo"
name="description"
ng-maxlength="512"
ng-model="$ctrl.selected"
rows="6"></textarea>
Ok, so I am going to explain that a little.
I have modal window like that:
I want to edit existing comments in this window. And so I want my comment appears instead of text: "Komentarz" (under: "Treść" after clicking in there). And I want that comment text to be editable, so I dont have to write it down again (put the whole text to that area). Is it make it a little better explained about my goal?

uib-popover-template not showing

I am trying to use a uib-popover-template on a font awesome icon as a sort of settings menu but can't get the popup to show. This is in the header of the page I am using:
<h3>{{vm.title}}
<i class="fa fa-ellipsis-v pull-right"
aria-hidden="true"
uib-popover-template="'options-panel.html'"
popover-placement="left"></i>
</h3>
And i have the ellipses in the right corner kind of like a 'more options' menu. options-panel.html is just 4-5 <select> dropdowns depending on the page that looks like this:
<div class="row">
<div class="form-group col-md-12">
<label for="viwemode">View Mode</label>
<select id="viewmode"
class="form-control"
ng-model="vm.currentViewer"
ng-options="view for view in vm.views"
ng-change="vm.viewChange();"></select>
</div>
<div class="form-group col-md-12"
ng-repeat="viewOption in vm.genericOptions">
<label for="{{viewOption.label}}">{{viewOption.label}}</label>
<select id="{{viewOption.label}}"
class="form-control"
ng-model="vm.config[viewOption.label]"
ng-options="v as k for (k,v) in viewOption.values"
ng-change="vm.optionChange(viewOption.label);"></select>
</div>
<div class="form-group col-md-12"
ng-repeat="viewOption in vm.viewerOptions">
<label for="{{viewOption.label}}">{{viewOption.label}}</label>
<select id="{{viewOption.label}}"
class="form-control"
ng-model="vm.config[viewOption.label]"
ng-options="value for value in viewOption.values"
ng-change="vm.optionChange(viewOption.label);"></select>
</div>
</div>
And lastly in the controller for the class I just have this object which has the template url in it:
vm.popover = {
template: '<a href uib-popover-template="\'options-panel.html\'" popover-placement="left"></a>'
};
I am not sure what I am missing but not even a popover will show let alone the one with my template in it. If I just do the ellipses (fa-icon) with uib-popover="test" the popover will show with 'test' in it so I do have the uib dependency correctly installed.
Consider this uib-popover-template plunker
I don't know your data structure but should work.
You don't need anymore
vm.popover = {
template: '<a href uib-popover-template="\'options-panel.html\'" popover-placement="left"></a>'
};
This line
uib-popover-template="'options-panel.html'"
Should be
uib-popover-template="options-panel.html"
Notice I removed the single quotes, uib-popover-template accepts an expression that will evaluate to the template location on your $scope. by passing your template path in single quotes you are only passing a plain string as an expression.
From the Docs
uib-popover-template - A URL representing the location of a template to use for the popover body

Ui-router, ng-repeat and ui state

I m developping an application in which I need to redirect the current user to a different state after a ressource creation.
Actually, I have a list of demands, and I need to show or create a quotation based on that demand.
Here's the view code :
<div class="landing-diags">
<div class="current-projects">
<div class="row project-summary" ng-repeat="demand in landingdiag.demandsList">
<div class="col-md-2 project-block first-block {{project.projectType}}">
<p class="project-strong">{{demand.user.firstname}} {{demand.user.lastname}}</p>
</div>
<div class="col-md-2 project-block">
<p class="project-strong">{{demand.creationDate | date:"dd/MM/yyyy"}}</p>
</div>
<div class="col-md-4">
</div>
<div class="col-md-2">
<div ng-if="!demand.quotation">
<button ng-click="landingdiag.createQuotation(demand)" class="btn btn-primary pull-right bar-btn">Create</button>
</div>
<div ng-if="demand.quotation">
<button ui-sref="app.state.concerned({id: demand._id})" class="btn btn-primary pull-right bar-btn">Show</button>
</div>
</div>
</div>
</div>
</div>
And here's the controller methods implied :
createQuotation (demand) {
this.DemandsService.createQuotation(demand).$promise.then((response) => {
this.redirectToQuote(demand);
});
}
redirectToQuote (demand) {
this.$state.transitionTo('app.state.concerned', {id: demand._id});
}
Problem
My problem is that I m never redirected when creating a quotation. If I console log the redirectToQuote method, I pass inside of it. So it seems that my problem is on the $state.go call.
However, when I try to redirect directly using the redirectToQuote method inside of my view on the "show" button like following :
<div ng-if="demand.quotation">
<button ng-click="landingdiag.redirectToQuote(demand)" class="btn btn-primary pull-right bar-btn">Accéder au devis</button>
</div>
I m well redirected to the concerned state
I am concerned about the this.redirectToQuote within createQuotation() which is called by then() as a callback. So the this object will definitely not be your controller.
Look at the first code snippet from todd: https://toddmotto.com/resolve-promises-in-angular-routes/
He is using bind.
You can also look at https://github.com/getify/You-Dont-Know-JS/tree/master/this%20%26%20object%20prototypes from awesome Kyle Simpson
or shorter from myself: http://blog.monkey-development.com/javascript/java/2015/12/18/javascript-this.html

Editing property from Object in ng-repeat from LocalStorage

I'm listing an array of objects saved into Localstorage in a table-like layout.
Each row displays data saved in a particular object. I want to be able to edit and update certain properties from the object once it has already been saved into LocalStorage.
This is how a couple of my objects looks like:
[{
"date":"2014 10 16",
"time":"20.22",
"car":"396",
"driver":"Seb",
"from":"A",
"destination":"B",
"pax":"3",
"arrival":"23.10"
},
{
"date":"2014 10 16",
"time":"23.22",
"car":"46",
"driver":"Eric",
"from":"C",
"destination":"E",
"pax":"3",
"arrival":"00.10"
}]
So far my frontend code displaying the Destination property looks like this:
HTML
<div class="col-md-3"
ng-show="editItem == false"
ng-hide="editItem">{{record.destination}}</div>
// Shows current value
<div class="col-md-3"
ng-show="editItem == true"
ng-hide="!editItem">
<select class="form-control"
ng-model="locationList2"
ng-options="location.place for location in locationlist | orderBy:'place'">
<option value="">Destination</option>
</select>
</div>
// Shows select with options to be picked to update property
<div class="col-md-1">
<button ng-click="editItem = !editItem"
ng-show="!editItem">Edit</button>
<button ng-click="editData(record); editItem = !editItem"
ng-show="editItem">Ok</button>
</div>
//Toggles between current value and select and triggers editData function
Relevant JS:
$scope.editData = function (record) {
record.destination = $scope.locationList2;
jsonToRecordLocalStorage($scope.recordlist);
}
So far when I trigger editData it just deletes the Destination property, it doesn't update it with the model of locationList2 from the Select.
What am I missing?
EDIT
Here's the complete ng-repeat piece of code:
<div class="row msf-row" ng-repeat="record in recordlist | filter: search">
<div class="col-md-1">{{record.time}}</div>
<div class="col-md-1"><strong>{{record.car}}</strong></div>
<div class="col-md-1">{{record.driver}}</div>
<div class="col-md-3">{{record.from}}</div>
<div class="col-md-3"
ng-show="editItem == false"
ng-hide="editItem">
{{record.destination}}
</div>
<div class="col-md-3"
ng-show="editItem == true"
ng-hide="!editItem">
<select class="form-control"
ng-model="locationList2"
ng-options="location.place for location in locationlist | orderBy:'place'">
<option value="">Destination</option>
</select>
</div>
<div class="col-md-1">{{record.pax}}</div>
<div class="col-md-1">
<button
ng-click="editItem = !editItem"
ng-show="!editItem">
<i class="fa fa-pencil"></i>
</button>
<button
ng-click="editData(record); editItem = !editItem"
ng-show="editItem">
<i class="fa fa-check"></i>
</button>
</div>
</div>
Also, I here's a Plunkr to ilustrate the issue!
Add a driver, car code and location before starting to see the app running and the mentioned problem.
You could use angular-local-storage as an abstraction over LocalStorage API.
If you want to just hack it, you can do something along localStorage.setItem('data', JSON.stringify(data)) when setting data and use JSON.parse(localStorage.getItem('data')) to extract it. LocalStorage doesn't deal with objects by default so we have to serialize it.
Regardless of the solution you choose, it could be a good idea to extend your edit a bit:
$scope.editData = function (recordlist) {
$scope.recordlist.destination = $scope.locationList2;
// replace whole LocalStorage data here now. no need to "patch" it
updateLocalStorage('data', <data containing your objects goes here>);
}
If you have multiple ways to modify the data and want to avoid explicit update, you could set up a watcher instead:
$scope.$watch(<data name goes here>, function(newVal) {
// update your LocalStorage now
});
Why it fails with ng-repeat?
The reason you see the behavior is quite simple. $scope.locationList2 is a single variable that gets bound for each member created by ng-repeat. That explains why it stays empty during edit.
You will need to bind the data using some other way. Consider binding it directly to your record models. Example: AngularJS - Using $index in ng-options .
Solution
The original code had bits like this:
JS:
$scope.editData = function (record) {
record.destination = $scope.location;
jsonToRecordLocalStorage($scope.recordlist);
};
HTML:
<select class="form-control" ng-model="location" ng-options="location.place for location in locationlist | orderBy:'place'">
<option value="">Destination</option>
</select>
Note that the markup is inside a ng-repeat and effectively each item created by it points at the same location! This isn't good.
To make it work I changed it like this:
JS:
$scope.editData = function () {
jsonToRecordLocalStorage($scope.recordlist);
};
HTML:
<select class="form-control" ng-model="record.destination" ng-options="location.place as location.place for location in locationlist | orderBy:'place'">
<option value="">Destination</option>
</select>
As mentioned above the JS could be replaced by a watcher. The important thing to note here is that I bind the data directly to the records. That avoid hassle at editData and more importantly gets rid of the problematic ng-model reference.

Categories

Resources