UI-grid: How to access MODEL_COL_FIELD from custom function? - javascript

I need to call from external scope a function, which opens the $modal, and on closing the modal, returns the result.
<div class="ui-grid-cell-contents">
<input ng-class="colt + col.uid"
ng-model="MODEL_COL_FIELD" ng-click="grid.appScope.openModal()"/>
</div>
and the function
$scope.openModal = function () {
var dialogScope = $scope.$new();
dialogScope.result = '';
var modalInstance = $modal.open({
templateUrl: 'url here',
scope: dialogScope,
size: 'lg'
});
modalInstance.result.then(function() {
// here I need to assign dialogScope.result to ui-grid Cell variable (MODEL_COL_FIELD)
})
How can I update MODEL_COL_FIELD variable using my external scope function? It's probably available somewhere in grid.appScope

If I understand correctly, you are just trying to pass that row data into a modal. I suggest using this method, which will give you access to the row object itself. This will allow any edits to the row in the modal to be passed to the parent grid.
Using this method, you would not be passing the result and updating the row, but instead updating the row from the modal itself because you are using a reference to the row object.
I have left dialogScope.result, but it will not be necessary to have for what you are doing here.
Template
<div class="ui-grid-cell-contents">
<input ng-class="colt + col.uid"
ng-model="MODEL_COL_FIELD" ng-click="grid.appScope.openModal(row)"/>
</div>
Function:
$scope.openModal = function (row) {
var dialogScope = $scope.$new();
dialogScope.result = '';
dialogScope.rowEntity = row.entity;
var modalInstance = $modal.open({
templateUrl: 'url here',
scope: dialogScope,
size: 'lg'
});
modalInstance.result.then(function() {
// here I need to assign dialogScope.result to ui-grid Cell variable (MODEL_COL_FIELD)
})

Related

$scope is undefined in view but not in controller

I have a $scope that needs to show the iso code on select from a list of countries.
So the countries list is being fetched a $http call factory and it populates into a scope, so far so good here
///////// get countries ////////////////
tableFactory.getCountries().then(function(data){
$scope.presentCountries = data;
});
presentCountries will be sent into typeahead where the user will type for a country and select it, like so:
<div class="countrySearchField">
<div class="row">
<h3 class="searchTitle">Pick a country</h3>
</div>
<input type="text" class="form-control search-input" ng-model="countryPicked" uib-typeahead="presentCountry.name for presentCountry in presentCountries | filter:{name: $viewValue}:startsWith" typeahead-min-length="1" typeahead-on-select="onSelectCountry($item, $model, $label)" typeahead-editable="false"/>
</div>
Once it's selected, it will call the scope function onSelectCountry.
$scope.onSelectCountry = function($item, $model, $label){
$scope.brandCountryCode = $item.iso_code_2;
// $scope.brandCountryCode = $item;
console.log($scope.brandCountryCode);
}
I can see the data,$scope.brandCountryCode, in the console from console.log, but not in the modal view(overlay view).
<div class="row subtitleModalRow">
<h5 class="unlock-description">Please check the following parameters before merging</h5>
<!-- <p class="unlock-description" ng-bind-html="overlayMessage"></p> -->
<ul>
<li>Brand Country: {{brandCountryCode}}</li>
</ul>
</div>
I don't understand why it's not showing up, but I can see the console.log output. I'm suspecting is because the scope is under a function, but I thought if you set a value into a $scope, it should be available anywhere, please correct me if I'm wrong.
Also, it could be that the overlay view is a separate html file from the typeahead html. However, this overlay view has the controller, tablePageCtrl. The controller should be present in both html files.
this.openModal = function(type) {
this.type = type;
if(type == 'mergeRequest'){
var templateUrl = 'app/views/dataMerge/overlayMsg.html';
var backdropClass = 'auth-backdrop';
var controller = 'tablePageCtrl';
}
this.modalInstance = $uibModal.open({
animation: true,
templateUrl: templateUrl,
controller: controller,
windowTopClass: 'auth-template',
backdrop: 'static',
backdropClass: backdropClass,
});
};
I did a test, outside the function called $scope.test = 'test' in the controller, and I see the value in the overlay view. I have other scopes based onSelect function that are running into this situation, and they all are under a $scope function.
I added an initializer, $scope.brandCountryCode = '', but it didn't do anything. If I can solve this one, then the other ones should be fine.
Not sure what's going here, does anybody have any suggestions. Still new to Angular and your help will be appreciated. Thanks!
EDIT
full service code for the overlay modal:
(function() {
'use strict';
angular
.module('com.xad.se-tools')
.service('tableModalService', function($scope, $uibModal){
this.modalInstance = null;
this.type = null;
this.openModal = function(type) {
this.type = type;
if(type == 'mergeRequest'){
var templateUrl = 'app/views/dataMerge/overlayMsg.html';
var backdropClass = 'auth-backdrop';
var controller = 'tablePageCtrl';
}
this.modalInstance = $uibModal.open({
animation: true,
templateUrl: templateUrl,
// controller: 'AuthCtrl',
controller: controller,
windowTopClass: 'auth-template',
backdrop: 'static',
backdropClass: backdropClass,
scope: $scope
});
};
this.closeModal = function() {
this.modalInstance.dismiss('cancel');
}
});
})();
I think that you should set scope config option in your modal instance to set scope used in modal:
this.modalInstance = $uibModal.open({
animation: true,
templateUrl: templateUrl,
controller: controller,
windowTopClass: 'auth-template',
backdrop: 'static',
backdropClass: backdropClass,
scope: $scope
});
Please check angular bootstrap modal documenation here for more details.

Populate ng model from value

I am trying to populate the ng-model from a value, but don't want it to update until it is saved. To do this I have the following code;
Controller;
var SettingsController = function (roleService) {
var ctrl = this;
ctrl.rename = function(name) {
ctrl.account.name = name;
};
roleService.role.settings().then(function (result) {
ctrl.account = result.data.account;
}, function (result) {
console.log(result);
});
};
A simple controller, it gets the current settings from a service and sets it to the ctrl.
When the rename(name) is called I update the name of the account (for now it just updates the scope but soon it will update also the back-end)
To rename your account I have the following piece of code
<input type="text" data-ng-model="account.name" />
<button type="button" data-ng-click="ctrl.rename(account.name)">
Rename
</button>
I use controler as so ctrl == SettingsController
Now I use data-ng-model="account.name" to update the name. This is done so I only update the name when the button is called. The only issue is how do I get the ctrl.account.name value to the input, without bubbling it up.
I could add $scope to my controller with $scope.account but that seems overkill to me. Isn't there a way to copy/populate a ng-model from an other value or some kind?
To get to the controller I use the angular routerProvider;
$routeProvider
.when('/settings/', {
templateUrl: '/user/template/settings/',
controller: 'SettingsController',
controllerAs: 'ctrl'
});

Use http cookie value in an Angular template

I have angular working in one of my ASP.NET MVC applications. I am using two html templates with Angular Routing. One is a list of current Favorites that comes from the database and is serialized into json from my Web API and used by angular to list those items from the database.
The second html template is a form that will be used to add new favorites. When the overall page that includes my angular code loads, it has a cookie named currentSearch which is holding the value of whatever the last search parameters executed by the user.
I would like to inject this value into my angular html template (newFavoriteView.html) for the value of a hidden input named and id'd searchString.
I have tried using jQuery, but had problems, plus I would much rather do this inside of angular and somehow pass the value along to my template or do the work inside the view(template). However, I know the latter would be bad form. Below is the code I think is important for one to see in order to understand what I am doing.
Index.cshtml (My ASP.NET VIEW)
#{
ViewBag.Title = "Render Search";
ViewBag.InitModule = "renderIndex";
}
<div class="medium-12 column">
<div data-ng-view=""></div>
</div>
#section ngScripts {
<script src="~/ng-modules/render-index.js"></script>
}
Setting the cookie in the MVC Controller
private void LastSearch()
{
string lastSearch = null;
if (Request.Url != null)
{
var currentSearch = Request.Url.LocalPath + "?" +
Request.QueryString;
if (Request.Cookies["currentSearch"] != null)
{
lastSearch = Request.Cookies["currentSearch"].Value;
ViewBag.LastSearch = lastSearch;
}
if (lastSearch != currentSearch)
{
var current = new HttpCookie("currentSearch", currentSearch){
Expires = DateTime.Now.AddDays(1) };
Response.Cookies.Set(current);
var previous = new HttpCookie("lastSearch", lastSearch) {
Expires = DateTime.Now.AddDays(1) };
Response.Cookies.Set(previous);
}
}
}
render-index.js
angular
.module("renderIndex", ["ngRoute"])
.config(config)
.controller("favoritesController", favoritesController)
.controller("newFavoriteController", newFavoriteController);
function config($routeProvider) {
$routeProvider
.when("/", {
templateUrl: "/ng-templates/favoritesView.html",
controller: "favoritesController",
controllerAs: "vm"
})
.when("/newsearch", {
templateUrl: "/ng-templates/newFavoriteView.html",
controller: "newFavoriteController",
controllerAs: "vm"
})
.otherwise({ redirectTo: "/" });
};
function favoritesController($http) {
var vm = this;
vm.searches = [];
vm.isBusy = true;
$http.get("/api/favorites")
.success(function (result) {
vm.searches = result;
})
.error(function () {
alert('error/failed');
})
.then(function () {
vm.isBusy = false;
});
};
function newFavoriteController($http, $window) {
var vm = this;
vm.newFavorite = {};
vm.save = function () {
$http.post("/api/favorites", vm.newFavorite)
.success(function (result) {
var newFavorite = result.data;
//TODO: merge with existing topics
alert("Thanks for your post");
})
.error(function () {
alert("Your broken, go fix yourself!");
})
.then(function () {
$window.location = "#/";
});
};
};
favoritesView.html
<div class="container">
<h3>New Favorite</h3>
<form name="newFavoriteForm" ng-submit="vm.save()">
<fieldset>
<div class="row">
<div class="medium-12 column">
<input name="searchString" id="searchString" type="hidden"
ng-model="vm.newFavorite.searchString"/>
<label for="title">Name</label><br />
<input name="title" type="text"
ng-model="vm.newFavorite.name"/>
<label for="title">Description</label><br />
<textarea name="body" rows="5" cols="30"
ng-model="vm.newTopic.description"></textarea>
</div>
<div class="medium-12 column">
<input type="submit" class="tiny button radius" value="Save"/> |
Cancel
</div>
</div>
</fieldset>
</form>
</div>
My current attepts have been using jQuery at the end of the page after Angular has loaded and grab the cookie and stuff it in the hidden value. But I was not able to get that to work. I also thought about setting the value as a javascript variable (in my c# page) and then using that variable in angular some how. AM I going about this the right way?
Or should it be handled in the angular controller?...
I'm new to angular and the Angular Scope and a bit of ignorance are getting in the way. If any other info is needed I can make it available, thanks if you can help or guide me in the right direction.
You can do it by reading the cookie value using JavaScript, set it as a property of the $scope object and access it on the template.
//Inside your controllers
function favoritesController($http, $scope) {
//Get the cookie value using Js
var cookie = document.cookie; //the value is returned as a semi-colon separated key-value string, so split the string and get the important value
//Say the cookie string returned is 'currentSearch=AngularJS'
//Split the string and extract the cookie value
cookie = cookie.split("="); //I am assuming there's only one cookie set
//make the cookie available on $scope, can be accessed in templates now
$scope.searchString = cookie[1];
}
EXTRA NOTE
In AngularJS, the scope is the glue between your application's controllers and your view. The controller and the view share this scope object. The scope is like the model of your application. Since both the controller and the view share the same scope object, it can be used to communicate between the two. The scope can contain the data and the functions that will run in the view. Take note that every controller has its own scope. The $scope object must be injected into the controller if you want to access it.
For example:
//inject $http and $scope so you can use them in the controller
function favoritesController($http, $scope) {
Whatever is stored on the scope can be accessed on the view and the value of a scope property can also be set from the view. The scope object is important for Angular's two-way data binding.
Sorry if I'm misunderstanding or over-simplifying, but...assuming JavaScript can read this cookie-value, you could just have your controller read it and assign it to a $scope variable?
If JavaScript can't read the value, then you could have your ASP write the value to a JavaScript inline script tag. This feels yuckier though.
Update to show controller-as example.
Assuming your HTML looked something vaguely like this:
<div ng-controller="MyController as controller">
<!-- other HTML goes here -->
<input name="searchString" id="searchString" type="hidden" ng-model="controller.data.currentSearch"/>
Then your controller may look something like this:
app.controller('MyController', function ($scope, $cookies) {
$scope.data = {
currentSearch: $cookies.currentSearch
};
// Note that the model is nested in a 'data' object to ensure that
// any ngIf (or similar) directives in your HTML pass by reference
// instead of value (so 2-way binding works).
});

Can't pass ID and call Controller from ajax or AngularJS

I have a table of objects, and I want to pass their ID on click, and without refresh populate a div or table, I've tried with AJAX and angular but can not pass ID.
If I fix the ID on a specific number it works.
In the View:
<script>
function CountryController($scope, $http) {
$http.get("/api/SportApi/GetCountry/").success(function (response) {
$scope.controllerFunction = function (value) {
console.log(value);
}
obj = JSON.parse(response);
$scope.country = angular.fromJson(obj);
});
}
</script>
<a class="item item-thumbnail-left" ng-href="#/api/SportApi/GetCountry/{{x.id}}" ng-click="CountryControler(x.id)">
click for countries
</a>
Could you try this:
function CountryController($scope, $http, id) {
console.log(id)
$http.get("/api/SportApi/GetCountry/").success(function (response) {
$scope.controllerFunction = function (value) {
console.log(value);
}
obj = JSON.parse(response);
$scope.country = angular.fromJson(obj);
});
}
On your view, you should have:
<a class="item item-thumbnail-left" href ng-click="CountryControler(x.id)">click for countries</a>
where href will stop the link from reloading the page and the ng-click will call a method on your controller.
In your controller, you should define that function on the scope variable:
var myApp = angular.module('myApp',[]);
myApp.controller('ExamleController', ['$scope', function($scope) {
$scope.CountryController = function(id) {
$http.get("/api/SportApi/GetCountry/" + id).success(function (response) {
$scope.controllerFunction = function (value) {
console.log(value);
}
obj = JSON.parse(response);
$scope.country = angular.fromJson(obj);
});
}
}]);
Verify that you have bootstrapped angular js (by defining the root element of your html with ng-app).
Verify that you have attached the controller class to your view (by defining the controller html element with ng-controller).
You should also verify that you are getting the right id on the view when calling "x.id".
$scope.controllerFunction seems unnecessary in this case.

Angularjs- adding/removing dynamic html elements (dropdown)

here is my code-
http://plnkr.co/edit/oTWXbLIKOxoGTd4U0goD?p=preview
why is the days dropdown does not data bind with scope.demoDays, it is always empty?
is this the correct way to add dropdown dynamically? If user adds 5 dropdown, how to get the results , will ng-model="selectedDay" create an array of selection? any suggestions?
Thank you
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $compile) {
var counter = 0;
$scope.fields = [];
$scope.days =['Day','Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
$scope.addField = function() {
$scope.fields.push({name:"test " + counter++});
};
});
app.directive('demoDisplay', function($compile){
return {
scope:{
demoDisplay:"=", //import referenced model to our directives scope
demoDays:"="
},
link:function (scope, elem, attr, ctrl)
{
scope.$watch('demoDisplay', function(){ // watch for when model changes
elem.html("") //remove all elements
angular.forEach(scope.demoDisplay, function(d){ //iterate list
var s = scope.$new(); //create a new scope
angular.extend(s,d); //copy data onto it
console.log(scope.demoDays);
var template = '<label class="item item-input"><div class="style-select"><select ng-model="selectedDay" ng-options="day for day in scope.demoDays"></select><br></div></label>';
elem.append($compile(template)(s)); // compile template & append
});
}, true) //look deep into object
}
}
})
html
<button ng-click="addField()">Add Field</button>
<div demo-display="fields" demo-days="days"></div>
There is no need for $watch in your link function - you have already established two-way binding by specifying = on your scope property. And you can use a plain template, without having to compile.
templateUrl: 'template.html',
where template.html is:
<label class="item item-input">
<div class="style-select">
<select ng-model="demoDisplay.selection" ng-options="day for day in demoDays"></select>
<br>
</div>
</label>
Notice that the select is bound to demoDisplay.selection, which will be created on each field and be accessible on the parent scope via two-way binding. Also, note that within ng-options, I changed scope.demoDays to just demoDays. In a directive's template you only need to use the property's name to access a scope value.
You can use the directive inside ng-repeat to create additional fields when the button is clicked:
<div ng-repeat="field in data.fields">
<div demo-display="field" demo-days="days"></div>
</div>
Here is a working plunker: http://plnkr.co/edit/pOY0l18W7wEbfSU7DKw2?p=preview
Any easy fix to get it working.
In your var template you have scope.demoDays.
Simply change this to demoDays. You are already in this scope so using it again isn't necessary.

Categories

Resources