Directive template with Input + ng-model = magic? - javascript

I'm quite frustrated and apologize in advance for poorly formulated question.
I've created derictive for simple list editing:
angular.module('myApp').
directive('variableList', function () {
return {
restrict: 'AE',
templateUrl: 'variableList.html',
replace: true,
scope: {
value: '='
},
controller: [
'$scope', '$element', '$attrs', '$transclude',
function($scope) {
$scope.removeListItem = function (index) {
$scope.value.splice(index, 1);
};
$scope.addListItem = function () {
$scope.value.push($scope.nextListItem);
$scope.nextListItem = null;
};
}
]
};
});
and template
<div class="variable-list">
<div class="variable-list-items">
<div class="row collapse variable-list-item" ng-repeat="(index, val) in value">
<div class="small-11 columns variable-list-item-value">
<input type="text" ng-model="val" />
</div>
<div class="small-1 columns">
<button class="button alert prefix no-margin icon-minus"
ng-click="removeListItem(index)"></button>
</div>
</div>
</div>
<div class="row collapse variable-list-controls">
<div class="small-11 columns">
<input type="text" ng-model="nextListItem" />
</div>
<div class="small-1 columns">
<button ng-class="{disabled: !nextListItem}"
ng-click="addListItem()"
class="button success prefix no-margin icon-plus"></button>
</div>
</div>
</div>
the important part of template if
<input type="text" ng-model="val" />
In the end I have quite working ui
But inputs for existings items doesnt work! Nothing happen when I try to edit them. Input for new item, add and remove buttons works as intended.
Any ideas?
Edit
I've tried to bind model like this
<input type="text" ng-model="value[key]" />
I was able to edit input but it caused even more magic, after first keypress input loses focus.

Found answer here https://github.com/angular/angular.js/issues/1267
Basically you have to have a . in ng-model or the revers data binding does not work on primitives.

Related

ng-submit is not working in Laravel PHP framework

everyone, I have another question related to Laravel/AngularJS.
In my mini-project, I have form which user can post question in the form, but when I click submit button, there are no requests (from inspect in Google Chrome). However, I have a Log in interface, the button is working very well. I use the same logic, same html structure. And I am wondering how can I fix this problem.
I have been debugging this for 2 hours, have been Googling for a long time. Please help me out!!
Below are the codes.
// Add question page
<script type="text/ng-template" id="question.add.tpl">
<div ng-controller="QuestionAddController" class="question-add container">
<div class="card">
<form name="question_add_form" ng-submit="Question.add()">
<div class="input-group">
<label>Title</label>
<input type="text"
name="title"
ng-minlength="5"
ng-maxlength="255"
ng-model="Question.new_question.title"
required>
</div>
<div class="input-group">
<label>Description</label>
<textarea type="text"
name="desc"
ng-model="Question.new_question.desc">
</textarea>
</div>
<div class="input-group">
<button ng-disabled="question_add_form.$invalid"
class="primary"
type="submit">Submit</button>
</div>
</form>
</div>
</div>
</script>
// Service and Controller
.service('QuestionService', [
'$http',
'$state',
function ($http, $state) {
var me = this;
me.new_question = {};
me.go_add_question = function () {
console.log(1);
$state.go('question.add');
};
me.add = function () {
if (!me.new_question.title)
return;
$http.post('/api/question/add', me.new_question)
.then(function (r) {
console.log('r', r);
// if (r.data.status) {
// console.log(r.data);
// me.new_question = {};
// $state.go('home');
// }
}, function (e) {
console.log('e', e);
})
}
}
])
.controller('QuestionAddController', [
'$scope',
'QuestionService',
function (QuestionService, $scope) {
$scope.Question = QuestionService;
}
])
in QuestionService.add(), there is no "return value" (console.log('r', r);) in my browser.
I make sure routes and url are working fine by directly typing the address in browser. Any suggestion will be highly appreciated!
Thanks in advance!!!
Edit:
Besides, the button Add Question is not working, too. I have to use ui-sref to make it redirect to the target url, will this be the reason why the submit button is not working (like I use ui-sref not the ng-submit to redirect)
// Add question
<div class="navbar clearfix">
<div class="container">
<div class="fl">
<div class="navbar-item brand">somethingHere</div>
<form ng-submit="Question.go_add_question()" id="quick_ask" ng-controller="QuestionAddController">
<div class="navbar-item">
<input ng-model="Question.new_question.title" type="text">
</div>
<div class="navbar-item">
<button ui-sref="question.add" type="submit">Add question</button> <!--ui-sref="question.add"-->
</div>
</form>
</div>
<blablabla something not important here!!!!>
Your injections in the controller is the wrong order. Should be
.controller('QuestionAddController', [
'$scope',
'QuestionService',
function ($scope, QuestionService) {
$scope.Question = QuestionService;
}
])
EDIT:
The ordering itself does not really matter, but the controller function argument ordering must match the ordering in the array. E.g.
Correct:
['QuestionService', 'Service2', '$scope', function(QuestionService, Service2, $scope) { ...
Incorrect:
['QuestionService', 'Service2', '$scope', function(QuestionService, scope, Service2) { ...
The reason to define the controller with array is so that the code can be minified

ANGULARJS: directive inside another directive doesn't have access to ng-model from HTML

I recently had a coding challenge that I got rejected for because it was garbage. Didn't have a lot of time so I threw everything together in one giant HTML file/angular controller, so I'm in the middle of rewriting it in templates to try to make it more reusable. So far it's going well, but I'm having some trouble with an html template not being able to access ng-model. Whenever I console.log the ng-model, I get undefined.
Here's the top layer HTML:
<div class="col-md-8 box">
<div class="panel panel-default">
<div class="panel-heading">Companies</div>
<div class="panel-body">
<div ng-repeat="company in companies">
<div class="panel panel-default">
<div class="panel-heading">Name: {{company.name}} <button ng-click="companies[$index].editCompany = !companies[$index].editCompany" class="pull-right">EDIT COMPANY</button></div>
<div class="panel-body" ng-if="!companies[$index].editCompany">
<p>Address: {{company.address}}</p>
<p>Revenue: {{company.revenue}}</p>
<p>Phone Number: {{company.phone}}</p>
<button ng-click="getPeople(companies[$index]._id, $index); companies[$index].viewEmployees = !companies[$index].viewEmployees">People Who Work Here</button>
<div ng-if="companies[$index].viewEmployees">
<show-employees-list></show-employees-list>
</div>
</div>
</div>
<div ng-if="companies[$index].editCompany">
<edit-company-directive></edit-company-directive>
</div>
</div>
</div>
</div>
</div>
And here's the HTML for the directive:
<div class="employee-box" ng-repeat="employee in companies[$index].employees">
<span class="glyphicon glyphicon-edit pull-right" ng-click="companies[$index].editEmployee = !companies[$index].editEmployee; clickEdit()"></span>
<span class="glyphicon glyphicon-remove pull-right" ng-click="deletePerson(employee._id, $index, companies[$parent.$index].employees)"></span>
<div ng-if="!companies[$index].editEmployee">
<div>
<p><b>Name:</b> {{employee.name}}</p>
<p><b>Email:</b> {{employee.email}}</p>
</div>
</div>
<div ng-if="companies[$index].editEmployee" class="form-body">
<form name="editPersonForm" ng-submit="editPerson(employee._id, $parent.$parent.index, $parent.index)">
<input type="text" ng-model="nameEdit" id="nameEdit" placeholder="Employee" class="form-control" required></input>
<input type="text" ng-model="emailEdit" id="emailEdit" placeholder="Email" class="form-control" required></input>
<button type="submit" id="submitButton" class="btn btn-success form-actions">Submit</button>
</form>
</div>
</div>
And here's the directive code:
'use strict';
(function() {
angular
.module('sigFig')
.directive('showEmployeesList', showEmployeesList);
function showEmployeesList(sigFigFactory) {
var directive = {
restrict: 'E',
templateUrl: 'Directives/showEmployeesList/showEmployeesList.html',
scope: '=',
require: '^parentDirective',
link: link
};
return directive;
function link(scope, element, attra, controller) {
scope.deletePerson = function(id, index, employees) {
sigFigFactory.deletePerson(id).then(function(response) {
employees.splice(index, 1);
return response;
})
};
scope.editPerson = function(personId, index1, index2) {
scope.person = {
name: scope.nameEdit,
email: scope.emailEdit
};
console.log('person ', scope.person);
};
}
}
})();
I'm thinking it's some sort of scoping issue that I just don't see, and hoping someone can help. When I console.log that person object I get undefined for both properties.
it's good idea to use angular directive, and also you need to read more about it:
you just define scope as variable but it's object, and there isn't scope.nameEdit to console
app.directive("name", function() {
return {
templateUrl: "your.html", //it's string
restrict: 'E',
scope: { //it's object
param1: "=" //var
param2: "#" //string
param3: "&" //method and etc
},
link: function(scope){ //it's function
//scope.param1
//scope.param2
//scope.param3
}
}
})
<name param1="{foo: 'test'}" param2="hello" param3="callback"></name>
with directive you can pass everything from your basic view (controller) to the directive, you can $watch value on change in your controller and more options.

Apply $scope ng-click event to hidden element after it is displayed

Please ask me for better explanation. I have built a global search function into the header of my site. I want to display a separate input box for mobile search that uses the same ng-click event but the input isn't displayed when the page loads. I am having trouble getting the hidden input value on the mobile ng-click once it is displayed.
The areas of concentration are the search click function is not finding the correct ng-model when the function is triggered. I think it is because since the hidden elements are not available on load the ng-model="searchQueryStringMobile" isn't applied to the scope somehow.
My question is how do I get ng-model="searchQueryStringMobile" applied in the scope after it has been displayed posthumously or post-click ng-click="flipNav('search')" so that it does not return undefined when you activate the ng-click="loadSearchResults"?
Here is the code:
HTML:
<div ng-controller="HeaderCtrl as header" class="container">
<div id="jesusSearchTop">
<input ng-model="searchQueryString" class="jesusSearchInput autoCompSearch" type="search" placeholder="Search..." autocomplete="off" />
<select ng-model="searchDDL.item" class="jesusSearchSelect" ng-options="item.name for item in searchDDL track by item.id"></select>
<div class="jesusSearchHolder">
<img class="goSearch" ng-model="jesusSearch" ng-click="loadSearchResults('norm')" src="/EMR4/img/gui_icons/searchIcon.png" alt="Search EMR" />
</div>
</div>
<div id="siteControls">
<div id="siteSearch" class="siteControl" ng-click="flipNav('search')"></div>
</div>
<div ng-switch="dd" class="dropDown">
<div ng-switch-when="none" style="display:none"></div>
<div ng-switch-when="search" class="dropMenu listStyle4" id="Search">
<input ng-model="searchQueryStringMobile" class="jesusSearchInput" type="text" placeholder="Search..." autocomplete="off" />
<select ng-model="searchDDL.item" class="jesusSearchSelect" ng-options="item.name for item in searchDDL track by item.id"></select>
<div class="jesusSearchHolder">
<img class="goSearch" ng-model="jesusSearchMobile" ng-click="loadSearchResults('mob')" src="/EMR4/img/gui_icons/searchIcon.png" alt="Search EMR" />
</div>
</div>
</div>
<div class="clr"></div>
</div>
Controller:
app.controller('HeaderCtrl', function ($scope, $http, $location, populateDDL) {
$http.get(badge.credentials[7].home+'data.JSON')
.success(function(data, status, headers, config) {
$scope.header = data.header;
$scope.searchOptions = new populateDDL('tblWebMenuItems',badge.credentials[1].key).
then(function(response) {
$scope.searchDDL = response.tblWebMenuItems
$scope.searchDDL.item = $scope.searchDDL[0];
});
})
.error(function(data, status, headers, config) {
console.log(data+', '+status+', '+headers+', '+config);
});
$scope.flipNav = function(choice){
if ($scope.dd === choice) {
console.log(choice);
$scope.dd = "none";
}else {
$scope.dd = choice;
}
};
$scope.loadSearchResults = function(uv) {
var loader;
if (uv === "mob") {
loader = $scope.searchQueryStringMobile;
}else if (uv === "norm") {
loader = $scope.searchQueryString;
}
console.log(uv+' - '+loader);
if (loader == null || loader < 2) {
alert('Please refine your search and continue, Thank you!');
}else {
$location.path("/search/"+$scope.searchDDL.item.name.toLowerCase()+"/");
$location.search("type",$scope.searchDDL.item.name.toLowerCase());
$location.search("query", loader);
}
};
});
i have tested your code and found that it is because of the ng-switch.As ng-switch creates its own new scope which is child scope of its parent's, so if you use ng-model=$parent.searchQueryStringMobile , then it will work fine or If you use ng-show instead of ng-swtich ,it will work because ng-show doesnt create new child scope, it just sets the markup's css property display to noneand $parent allows you to access items of parent scope from child scope.In your example, $scope.searchQueryStringMobile is in the parent scope of ng-switch's scope. Here is the working plunk click
you can change your ng-switch markup to this
<div ng-switch="dd" class="dropDown" >
<div ng-switch-when="none" style="display:none"></div>
<div ng-switch-when="search" class="dropMenu listStyle4" id="Search">
<input ng-model="$parent.searchQueryStringMobile" class="jesusSearchInput" type="text" placeholder="Search..." autocomplete="off" />
<select ng-model="searchDDL.item" class="jesusSearchSelect" ng-options="item.name for item in searchDDL track by item.id"></select>
<div class="jesusSearchHolder">
<img class="goSearch" ng-model="jesusSearchMobile" ng-click="loadSearchResults('mob')" src="/EMR4/img/gui_icons/searchIcon.png" alt="Search EMR" />
</div>
</div>
</div>
Notice the ng-model for the input element in the above code.
Your problem is quite simple one. ng-switch just like ng-if creates new scope, so when you are using ng-model, yu are assign property to this new scope and not the scope used by your controller.
Solution would be to use controller as syntax or use property of some object created on scope. To illustrate this I create example for you.
As you can see {{a}} does not work outside new scope, but {{x.b}} works just fine.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app ng-init="x = {}; show = 'first'">
<button type="button" ng-click="show = 'first'">show first</button><br>
<button type="button" ng-click="show = 'second'">show second</button><br>
a = {{a}}<br>
x.b = {{x.b}}
<div ng-switch="show">
<div ng-switch-when="first">
<input type="text" ng-model="a">
</div>
<div ng-switch-when="second">
<input type="text" ng-model="x.b">
</div>
</div>
</div>

How do I access ng-show directive with ng-click? AngularJS

I just started learning so I'm creating a todo app.
I'm trying to show a div when I click on the edit button to edit my task.
this is my html
<div ng-controller='TasksCtrl'>
<div ng-repeat='(key, task) in tasksList' class='task-list'>
<div class='easy'>
<div class='div-list-style'></div>
<div id='task-{{key}}' style='cursor:pointer;z-index:5'
ng-click='editTask()' data-key='{{key}}' class='options
pull-right glyphicon glyphicon-pencil'>
</div>
<div class='task-desc' ng-bind='task.description'></div>
<div ng-hide='taskEdit = true'>FORM</div>
</div>
</div>
</div
This is my controller
todoApp.controller('TasksCtrl',['$scope', 'saveTaskService', function($scope, saveTaskService){
$scope.editTask= function(){
todoApp.directive('taskEdit', function(){
return function(scope, element){
//so I guess over here I need do ngHide = 'false' ? //
alert(element.attr('data-key'));
};
});
};
}]);
Here is a quick solution, you have a scope variable called taskShow that will tell ng-hide when to show it, then on ng-click you will trigger a function that will toggle that value:
<div ng-controller='TasksCtrl'>
<div ng-repeat='(key, task) in tasksList' class='task-list'>
<div class='easy'>
<div class='div-list-style'></div>
<div id='task-{{key}}' style='cursor:pointer;z-index:5'
ng-click='toggleHide(key)' data-key='{{key}}' class='options
pull-right glyphicon glyphicon-pencil'>
</div>
<div class='task-desc' ng-bind='task.description'></div>
<div ng-show='taskShow[key]'>FORM</div>
</div>
</div>
</div>
Controller:
todoApp.controller('TasksCtrl',['$scope', 'saveTaskService', function($scope, saveTaskService){
$scope.taskShow = {};
$scope.toggleHide = function (key) {
$scope.taskShow[key] = !$scope.taskShow[key];
};
}]);
Edit: switched ng-hide to ng-show so the divs are hidden by default and only shown when the other is clicked.

I am trying to call text from input using angular js

I am trying to call text that has been added to an input using Angular JS, however in my console log I keep getting undefined.
<div ng-controller="favouritesController" class="col-xs-12 favList">
<input type="text" ng-model="newFav" ng-keyup= "add($event)" class="col-xs-12 FavInput" placeholder="Add A Favourite">
<ul>
<li ng-repeat="weatherList in weatherLists" class="col-xs-12">
<span class="col-xs-12 col-sm-8">{{weatherList._id + ' / ' + weatherList.place}}</span>
<div class="col-xs-12 col-sm-2">
<button type="button" name="button" class="deleFav" ng-click="delete(weatherList)">Delete</button>
<div class="col-xs-12">
<input type="text" ng-model="serverip"/>
<button ng-click="save(serverip)">Save</button>
</div>
</div>
</li>
</ul>
</div>
js code
myApp.controller('favouritesController', function($scope, $http, $rootScope, $route, $location) {
$scope.save = function(){
console.log($scope.serverip)
}
})
You don't need to pass the parameter to the save function (and your definition of save doesn't include it).
Change the button to:
<button ng-click="save()">Save</button>
Or either accept the parameter in the function declaration:
$scope.save = function(serverip){
console.log(serverip)
}
ng-repeat creates a new scope, inheriting from the scope above it. You are assigning serverip to this newly created scope. Thus, $scope in the favouritesController's context has no record of this. You should accept a parameter in your save function and log that (as you are passing this function the argument, anyways.)
Edit:
or, as an alternative... Expose a property that will be inherited by ng-repeat:
Controller:
myApp.controller('favouritesController', function($scope, $http, $rootScope, $route, $location) {
$scope.ip = { serverip:'' };
$scope.save = function(){
console.log($scope.ip.serverip)
}
});
Template
<div ng-controller="favouritesController" class="col-xs-12 favList">
<input type="text" ng-model="newFav" ng-keyup= "add($event)" class="col-xs-12 FavInput" placeholder="Add A Favourite">
<ul>
<li ng-repeat="weatherList in weatherLists" class="col-xs-12">
<span class="col-xs-12 col-sm-8">{{weatherList._id + ' / ' + weatherList.place}}</span>
<div class="col-xs-12 col-sm-2">
<button type="button" name="button" class="deleFav" ng-click="delete(weatherList)">Delete</button>
<div class="col-xs-12">
<input type="text" ng-model="ip.serverip"/>
<button ng-click="save()">Save</button>
</div>
</div>
</li>
</ul>
</div>

Categories

Resources