Making visible and refreshing a DOM element : Angular JS - javascript

Not very familiar with Angular JS but here is what I have and what I want:
<div ng-app="MyApp" ng-controller="appController">
<div class="input-group">
<input class="form-control enableEnter" type="text" ng-model="action"/>
<div class="input-group-btn">
<button class="btn btn-primary" ng-click="search()">Search</button>
</div>
</div>
<ul class="dropdown-menu" id="list" ng-show = {{display}} >
<li> hello </li>
<li class="dropdown" ng-repeat="x in actions">
{{x.name}}
</li>
</ul>
</div>
My js file :
MyApp.controller('appController', ['$scope', function ($scope) {
$scope.actions = [];
$scope.display=false;
$scope.search = function () {
$.get("http://localhost:8080/get/something/" + $scope.action)
.success(function (response) {
console.log(response);
$scope.actions = response['RESPONSE'];
$scope.display=true;
}).error(function (jqXHR, textStatus, errorThrown) {
console.error("Error retrieving something list", textStatus, errorThrown);
});
}
}]);
The $scope.actions is empty initialized in the controller however on clicking the "Submit" button , we get a list of actions which are populated in actions. I want to show this list below the form. For this I am changing the value of ng-show when submit is clicked. Should this automatically update the <UL> element? Because I can't seem to see anything even after clicking.

You don't need to interpolate {{ }} inside an ng-show:
<ul class="dropdown-menu" id="list" ng-show="display" >
<li> hello </li>
<li class="dropdown" ng-repeat="x in actions">
{{x.name}}
</li>
</ul>
You might also want to look into an ng-if as well.

Problem is in below statement
<ul class="dropdown-menu" id="list" ng-show = {{display}} >
`change ng-show= {{display}} to ng-show='display'`
Check this working example - In this example, I have created submit button after clicking on ,I have change value of display and stored some dummy data.
https://jsfiddle.net/Shital_D/fc0L5pe3/2/

Related

Multiselect Dropdown - Display Selected Data on Button

I have a multiselect dropdown that fetches data from the database. There are preselected data that I need to display on page load instead of displaying the "Please Select" word. I am using angularjs and javascript. How can I possibly do that. My code looks like this:
<div class="btn-group col-md-6 pull-right">
<button data-toggle="dropdown" class="col-xs-12 btn btn-primary dropdown-toggle" >---Please select---{{item.skin_type_name}}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li ng-repeat="item in SkinType">
<input type="checkbox" id={{item.skin_type_id}} name="NAME2" value="{{item.skin_type_id}}" ng-checked="skintypeID[item.skin_type_id]==item.skin_type_id" ng-click="skntypclk(item.skin_type_id)" ng-disabled="currreadstypepro==1" ng-required="curstyp==1"><label>{{item.skin_type_name}}</label>
</li>
</ul>
I am using an API fetching data from the database and it looks like this one:
editorService.editSkintype(id)
.then(function(data){
$rootScope.loadercount--;
console.log($rootScope.loadercount);
skintypeIDArr = {};
angular.forEach(data.data, function(value) {
angular.forEach(value, function(value, key) {
if(key == "skin_type_id"){
skintype[value] = value;
skintypeIDArr[value] = value;
}
});
});
$scope.skintypeID = skintypeIDArr;
})
How can I display the preselected value on button instead of Please select? The data can only be displayed once I edit the values but what i need is to display the preselected value on page load. How can I do that?
Make sure to have the currently selected item in the scope. so the HTML would be:
<div class="btn-group col-md-6 pull-right">
<button data-toggle="dropdown" class="col-xs-12 btn btn-primary dropdown-toggle">{{selectedItem.skin_type_name}}<span class="caret"></span></button>
<ul class="dropdown-menu">
<li ng-repeat="item in SkinType">
<input type="checkbox" id={{item.skin_type_id}} name="NAME2" value="{{item.skin_type_id}}" ng-checked="skintypeID[item.skin_type_id]==item.skin_type_id" ng-click="skntypclk(item.skin_type_id)" ng-disabled="currreadstypepro==1" ng-required="curstyp==1"><label>{{item.skin_type_name}}</label>
</li>
</ul>
</div>
If so, then in your controller you could simply load the default value and then run the API call:
app.controller('ctrl', function($scope) {
$scope.selectedItem = {
skin_type_name: "Preselected Data"
};
// Now run the API call...
});
This way the preselected data will be set when the controller is loaded.
If you need it to be outside the controller, then declare the selectedItem in the $rootScope instead.

Assign Dynamic templates

I am trying to use KnockoutJS to develop a wizard for my asp.net app.
This is my first attempt at using KO.
What I am trying to achieve is assign dynamic templates based on a Click event of an anchor tag.
My HTML looks like this
<script id="ParamHomeTmpl" type="text/html">
<section class="alert alert-info">
<div class="panel-heading h3 blackincolor"><i class="fa fa-exclamation-circle redincolor" style="margin-right: 5px"></i>Please Select Parameter Type</div>
<ul class="blackincolor list-group">
<li><a class="list-group-item list-group-item-info" data-bind="click: templateToUse" href="#" id="InputType"><b>Input Type:</b> Gives an Option to Select your Key-Value Pairs.</a></li>
<li><a class="list-group-item list-group-item-success" data-bind="click: templateToUse" href="#" id="ListType"><b>List Type:</b> You can type in a Key and insert a list of values and select one of the values that you created.</a></li>
</ul>
</section>
</script>
<script id="InputTypeTmpl" type="text/html">
<div>
<p>Input Type</p>
</div>
</script>
<script id="ListTypeTmpl" type="text/html">
<div>
<p>ListType</p>
</div>
</script>
<script id="BlankTmpl" type="text/html">
<div>
<p>Blank</p>
</div>
</script>
<div class="tab-pane" id="SelectParamType" data-bind="template: { name: templateToUse }">
</div>
And finally the actual JS is:
var viewModel = {
currTemplate: function () {
return "paramHome";
},
paramType: ko.observable("Metadata")
};
viewModel.secondStep = function (data, event) {
// return (event.target.id);
console.log(data);
};
viewModel.templateToUse = function (data, event) {
try {
alert(event.target.id);
switch (event.target.id) {
case "InputType":
return "InputTypeTmpl";
case "ListType":
return "ListTypeTmpl";
default:
return "BlankTmpl";
}
}
catch (err) { return "ParamHomeTmpl" ;}
};
ko.applyBindings(viewModel);
The issue is that when I click the anchor tag from the first step "Select Param Type", the template is not swapped automatically based on the click event target.
I am not sure what am I doing wrong here.
Jsfiddle: http://jsfiddle.net/sourabhtewari/c8tm1193/
I think your approach -- using templates -- is wrong. Dynamic HTML is what the if binding is for. The only legitimate use for templates (imo) is recursive HTML structure.
Update I no longer subscribe to this view. Templates are useful for recursive HTML and when a section of code may take several forms. Bind to a variable and update the variable with the proper template name. Original answer continues below.
I've made the click bindings set an observable that controls which section is displayed.
var viewModel = {
section: ko.observable('blank'),
paramType: ko.observable("Metadata")
};
viewModel.secondStep = function(data, event) {
// return (event.target.id);
console.log(data);
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<section class="alert alert-info">
<div class="panel-heading h3 blackincolor"><i class="fa fa-exclamation-circle redincolor" style="margin-right: 5px"></i>Please Select Parameter Type</div>
<ul class="blackincolor list-group">
<li><a class="list-group-item list-group-item-info" data-bind="click: section.bind(0, 'input')" href="#" id="InputType"><b>Input Type:</b> Gives an Option to Select your Key-Value Pairs.</a>
</li>
<li><a class="list-group-item list-group-item-success" data-bind="click: section.bind(0, 'list')" href="#" id="ListType"><b>List Type:</b> You can type in a Key and insert a list of values and select one of the values that you created.</a>
</li>
</ul>
</section>
<div data-bind="if:section()=='input'">
<p>Input Type</p>
</div>
<div data-bind="if:section()=='list'">
<p>ListType</p>
</div>
<div data-bind="if:section()=='blank'">
<p>Blank</p>
</div>
I know this is an old question, but I came across my previous answer and felt it needed to be fixed.
The main problem with your code is that you're using the function you've bound to the click as the template name. You should have a separate observable for the template name, and the function should set its value:
<div class="tab-pane" id="SelectParamType" data-bind="template: currTemplate">
...
var viewModel = {
currTemplate: ko.observable('ParamHomeTmpl'),
paramType: ko.observable("Metadata")
};
Also, you have no breaks in your switch, so it always falls through to default, though you fixed this in your answer.
A secondary problem is that clicking on the bold text in the link causes event.target to be the <b> element rather than the <a>, so you have no id. You can avoid this problem by binding the template name to the function call:
data-bind="click: templateToUse.bind($root, 'InputTypeTmpl')"
and using the data parameter in the function, which then becomes very simple:
viewModel.templateToUse = function(data) {
viewModel.currTemplate(data);
};
In fact, you can do away with the function entirely and bind directly to the template name observable:
data-bind="click: currTemplate.bind($root, 'InputTypeTmpl')"
var viewModel = {
currTemplate: ko.observable('ParamHomeTmpl'),
paramType: ko.observable("Metadata")
};
viewModel.secondStep = function(data, event) {
// return (event.target.id);
console.log(data);
};
viewModel.templateToUse = function(data) {
viewModel.currTemplate(data);
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<script id="ParamHomeTmpl" type="text/html">
<section class="alert alert-info">
<div class="panel-heading h3 blackincolor"><i class="fa fa-exclamation-circle redincolor" style="margin-right: 5px"></i>Please Select Parameter Type</div>
<ul class="blackincolor list-group">
<li><a class="list-group-item list-group-item-info" data-bind="click: currTemplate.bind($root, 'InputTypeTmpl')" href="#" id="InputType"><b>Input Type:</b> Gives an Option to Select your Key-Value Pairs.</a>
</li>
<li><a class="list-group-item list-group-item-success" data-bind="click: currTemplate.bind($root, 'ListTypeTmpl')" href="#" id="ListType"><b>List Type:</b> You can type in a Key and insert a list of values and select one of the values that you created.</a>
</li>
</ul>
</section>
</script>
<script id="InputTypeTmpl" type="text/html">
<div>
<p>Input Type</p>
</div>
</script>
<script id="ListTypeTmpl" type="text/html">
<div>
<p>ListType</p>
</div>
</script>
<script id="BlankTmpl" type="text/html">
<div>
<p>Blank</p>
</div>
</script>
<div class="tab-pane" id="SelectParamType" data-bind="template: currTemplate">
</div>
The problem is fixed using
applyBindingsToNode
Code:
viewModel.templateToUse = function(data, event) {
try {
switch (event.target.id) {
case "InputType":
templateType = "InputTypeTmpl";
break;
case "ListType":
templateType = "ListTypeTmpl";
break;
case "FileType":
templateType = "FileTypeTmpl";
break;
case "DataBaseType":
templateType = "DataBaseTypeTmpl";
break;
default:
return "BlankTmpl";
}
} catch (err) {
return "BlankTmpl";
}
ko.applyBindingsToNode(document.getElementById("Attributes"), {
template: {
name: templateType
}
});
Fiddle: http://jsfiddle.net/sourabhtewari/c8tm1193/1

Nested Angular Switches?

I'm building a MEAN SPA and the current page I'm working on displays the users in the database. I'm pretty new to Angular so I'm still trying to wrap my head around it.
I have a parent container of which the content is controlled by an <ng-switch> and switches to show the relevant content depending on whether the user has clicked 'view all' or 'add new'. This works fine.
What I'm aiming to do now is when the user clicks on a user that's displayed in 'view-all', I want the content to switch to a view containing that users details where they can then go and edit the profile etc. What would be the best way to achieve this?
My HTML is set up like so:
Main staff view
<div class="staff" ng-controller="staffController">
<div class="side-menu">
<h2>Staff</h2>
<ul>
<li><a ng-click="tab='view-all'"><i class="fa fa-user"></i> View All</a></li>
<li><a ng-click="tab='add-new'"><i class="fa fa-plus"></i> Add New</a></li>
</ul>
</div>
<div class="page-content" ng-switch on="tab">
<div ng-switch-when="view-all" class="tab-content">
<staff-view-all></staff-view-all>
</div>
<div ng-switch-when="add-new" class="tab-content">
<staff-add-new></staff-add-new>
</div>
</div>
</div>
Directives:
.directive('staffViewAll', function () {
return {
restrict: 'E',
templateUrl: 'partials/staff/view-all.ejs'
}
})
.directive('staffAddNew', function () {
return {
restrict: 'E',
templateUrl: 'partials/staff/add-new.ejs'
}
})
view-all.ejs
<h2>View all staff</h2>
{{ users.length }} users in system
<ul>
<li ng-repeat="user in users"> <!-- click this and you see the singular view -->
<img ng-src="{{user.avatar}}?dim=100x100" />
<h3>{{user.username}}</h3>
<h4>{{user.email}}</h4>
</li>
</ul>
Use another ng-switch to switch to detailed view for the selected user.
Something like this: jsfiddle
<div ng-switch-when="list">
<ul>
<li ng-repeat="fruit in fruits">
{{fruit}}
</li>
</ul>
</div>
<div ng-switch-when="details">
<p>Details for {{ selectedFruit }}</p>
Back to list
</div>
Controller:
$scope.showDetail = function (fruit) {
$scope.selectedFruit = fruit;
$scope.moduleState = 'details';
}
$scope.showList = function()
{
$scope.moduleState = 'list';
};

How to do a foreach binding using KnockoutJS in Bootstrap-themed dropdown

I'm developing a small notifications-like module, where the user can see his 5 latest activities that are logged in the DB (MSSQL). The values that I need are all there, but for some reason knockout binding is not working. Here are code snippets:
<div class="dropdown-menu toolbar pull-right" data-bind="with: layoutLogsModel">
<h3 style="border: none;">Recent activities:</h3>
<!-- "mailbox-slimscroll-js" identifier is used with Slimscroll.js plugin -->
<ul id="mailbox-slimscroll-js" class="mailbox" data-bind="foreach: layoutLogsModel.notification">
<div class="alert inbox">
<a href="javascript:void(0)">
<i class="icon-book" style="color: orange;"></i>
Some text
</a>
<br>
Some text #2
</div>
</ul>
</div>
For now, I only want to display random text for every item that is in the observableArray.
ViewModel is the following:
var layoutLogsModel = {
notification: ko.observableArray()
};
function getLastFiveActivities() {
get(apiUrl + "Logs/GetLastFiveActivities", { ClientUserID: loggedUserID }, function (data) {
layoutLogsModel.notification(data);
});
}
And every time I call this function, the list is empty (IMAGE)
(the function is called on click, and absolutely no errors are shown in the console).
What is it that I am doing wrong?
EDIT:
The thing was, I forgot to execute ko.applyBindings for that viewModel. Then, I changed the HTML to look like this:
<ul id="mailbox-slimscroll-js" class="mailbox" data-bind="foreach: notification">
<div class="alert inbox">
<a href="javascript:void(0)">
<i class="icon-user" style="color: green;"></i>
<span data-bind="text: $data"></span>
</a>
</div>
</ul>
Aslo, I modified the get function slightly, like this:
function getLastFiveActivities() {
get(apiUrl + "Logs/GetLastFiveActivities", { ClientUserID: loggedUserID }, function (data) {
layoutLogsModel.notification(data.Notification);
});
}
(changed data to data.Notification based on the MVC model property that contains the array)
After all that, the data was available immediately.
try removing the layoutLogsModel from the foreach, you are already using it with the binding "with", so eveything in that div will be part of layoutLogsModel.
<div class="dropdown-menu toolbar pull-right" data-bind="with: layoutLogsModel">
<h3 style="border: none;">Recent activities:</h3>
<!-- "mailbox-slimscroll-js" identifier is used with Slimscroll.js plugin -->
<ul id="mailbox-slimscroll-js" class="mailbox" data-bind="foreach: notification">
<div class="alert inbox">
<a href="javascript:void(0)">
<i class="icon-book" style="color: orange;"></i>
Some text
</a>
<br>
Some text #2
</div>
</ul>
</div>

How to update a textfield based on other form elements

I'm writing a little database query app.
What i'm trying to do: Each time a checkbox is clicked, i'd like for a query that includes the selected fields to be generated and inserted into the textarea.
The problem: For some reason, with every click, its showing the query from the previous click event, not the current one.
Here's the markup:
<div class="application container" ng-controller="OQB_Controller">
<!-- top headr -->
<nav class="navbar navbar-default navbar-fixed-top navbar-inverse shadow" role="navigation">
<a class="navbar-brand">
Algebraix Database Client
</a>
<ul class="nav navbar-nav navbar-right">
<!--<li>Clear Queries</li>-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-import"></span> Load Data <b class="caret"></b></a>
<ul class="dropdown-menu">
<li>Default Data</li>
<li>Custom Import</li>
<!-- <li class="divider"></li> -->
</ul>
</li>
<li>
<a href="" class="queries-clear">
<span class="glyphicon glyphicon-remove"></span> Clear Queries
</a>
</li>
</ul>
</nav>
<!-- left column -->
<div class="col-md-4">
<div class="well form-group">
<ul>
<li ng-repeat="option in options">
<input type="checkbox" class="included-{{option.included}}" value="{{option.value}}" ng-click="buildQuery()" ng-model="option.included"> {{option.text}}
</li>
</ul>
</div>
</div>
<!-- right column -->
<div class="col-md-8">
<form role="form" id="sparqlForm" method="POST" action="" class="form howblock">
<div class="form-group">
<!--<label>Query</label>-->
<textarea type="text" name="query" class="form-control" rows="10" placeholder="Write your SPARQL query here">{{query}}</textarea>
</div>
<div class="form-group">
<input type="submit" class="btn btn-primary" value="Submit Query" data-loading-text="Running Query..." />
</div>
</form>
</div>
</div>
And in my controller, i am doing the following:
var OQB_Controller = function($scope) {
console.log('OQB_CONTROLLER');
$scope.query = 0;
$scope.options = [
{ text: "checkbox1", value: "xyz123", included: false }
,{ text: "checkbox2", value: "abcRRR", included: false }
,{ text: "checkbox2", value: "abcRRR", included: false }
];
$scope.buildQuery = function() {
console.log('click');
var lines = [];
lines.push("SELECT *");
lines.push("WHERE {");
lines.push(" ?s ?p ?o .");
for(var i = 0; i<$scope.options.length; i++) {
var line = $scope.options[i];
console.log( line.value, line.included, i );
if( line.included ) {
lines.push(" OPTIONAL { ?s "+line.value+" ?o } .");
}
}
lines.push("}");
lines.push("LIMIT 10");
var _query = lines.join("\n");
$scope.query = _query;
};
};
To reiterate, every time the build query method is called, the state of the included booleans is from one click event prior. this has the symptoms of the classic javascript problem of the keyup vs keydown and the state of the event... however, i'm not sure if that is what is happening here.
is there a better way to do build the query (than what i'm currently doing) and populate the textarea based on the checked boxes?
use ng-change instead of ng-click because it is more appropriate for this particular desired behavior. See the ng-change documentation below:
The ngChange expression is only evaluated when a change in the input
value causes a new value to be committed to the model.
It will not be evaluated:
if the value returned from the $parsers transformation pipeline has
not changed if the input has continued to be invalid since the model
will stay null if the model is changed programmatically and not by a
change to the input value

Categories

Resources